0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rubyで文字列のタイム表示を昇順に並び替える

Last updated at Posted at 2022-03-15

やりたいこと

文字列のタイム表示を昇順で並び替える。

条件

  • 文字列の形式は00:00.00 (分 : 秒 . 小数点以下2ケタ)
  • 想定のタイム範囲は05:00.00から10:59.99
  • 件数はおよそ250件

環境

  • Ruby 3.1.0p0
  • macOS 10.15.7

文字列のサンプルをつくる

Integer#timesKernel.#randTime#localTime#strftimeを使って250件のサンプルをつくった。

array = []
250.times { array << rand(Time.local(2022,3,14,1,5,0,0,0)..Time.local(2022,3,14,1,10,59,999) ) }

#Timeオブジェクトを`Time#strftime`を使って文字列に成形する
samples = array.map{|t| t.strftime("%M:%S.%2N")}
#=> ["10:11.12", "05:30.87", "09:59.53", "08:25.66", "07:57.37",...... "08:28.48", "07:17.87", "09:24.65", "10:47.52", "05:21.44"]

並び替えのベンチマークテストをする

[2022-03-16]修正

処理内容や数量によってsortsort_byのどちらが速いかが変わるようなので、Benchmarkモジュールのbm関数を使ってテストしてみる。

試したのは次の4つ。

  • sort_by
    • 文字列からintegerに変換してからsort
    • 文字列のままsort
  • sort
    • 文字列からintegerに変換してからsort
    • 文字列のままsort
require 'benchmark'

#レポート名をつけて計測する
Benchmark.bm(10) do |x|
	x.report('sort_by_i') {samples.sort_by { |s| s.delete(":.").to_i } }
	x.report('sort_by_s') {samples.sort_by { |s| s } }
	x.report('sort_i')    {samples.sort { |a, b| a.delete(":.").to_i <=> b.delete(":.").to_i } }
	x.report('sort_s')    {samples.sort}
end

追記[2022-03-16]

@scivolaさんからコメントで色々と教えていただきgem.benchmark_driverでもテストを行ってみた。

その際、
.delete(":").delete(".").delete(":.")
samples.sort{|a,b| a <=> b}samples.sortに変更。

参考
benchmark-driver
https://github.com/benchmark-driver/benchmark-driver

まずbenchmark_driverをインストール。

$ gem install benchmark_driver

code

require 'benchmark_driver'

#テスト対象を文字列で記入
Benchmark.driver do |x|
	x.prelude <<~RUBY
		array = []
		250.times { array << rand(Time.local(2022,3,14,1,5,0,0,0)..Time.local(2022,3,14,1,10,59,999) ) }
		samples = array.map{|t| t.strftime("%M:%S.%2N")}
  RUBY
	x.report 'sort_by_i' , %{ samples.sort_by \{ |s| s.delete(":.").to_i \} }
	x.report 'sort_by_s' , %{ samples.sort_by \{ |s| s \} }
	x.report 'sort_i'    , %{ samples.sort \{ |a, b| a.delete(":.").to_i <=> b.delete(":.").to_i \} }
	x.report 'sort_s'    , %{ samples.sort }
end

結果

[2022-03-16]修正

benchmarkモジュールの結果

                 user     system      total        real
sort_by_i    0.000199   0.000005   0.000204 (  0.000191)
sort_by_s    0.000106   0.000000   0.000106 (  0.000106)
sort_i       0.002053   0.000006   0.002059 (  0.002049)
sort_s       0.000055   0.000001   0.000056 (  0.000055)

文字列のままsortを使うのが速いもよう。

レポートの見方はこちらの記事を参考にしました。
https://qiita.com/scivola/items/c5b2aeaf7d67a9ef310a

ちゃんと昇順に並び替えられているか確認。

p samples.sort

#=> ["05:00.13", "05:00.23", "05:00.56", "05:02.97", "05:03.29", ... "10:51.62", "10:54.19", "10:54.99", "10:55.26", "10:55.39"]

できてました。

ちなみにサンプル10件でテストした結果は以下。

#サンプル10件

                 user     system      total        real
sort_by_i    0.000021   0.000004   0.000025 (  0.000019)
sort_by_s    0.000006   0.000001   0.000007 (  0.000006)
sort_i       0.000042   0.000001   0.000043 (  0.000042)
sort_s       0.000003   0.000001   0.000004 (  0.000012)

やはり文字列のままsortを使うのが速そうです。

benchmark-driverの結果

Warming up --------------------------------------
           sort_by_i     7.769k i/s -      8.426k times in 1.084521s (128.71μs/i)
           sort_by_s    12.458k i/s -     13.288k times in 1.066642s (80.27μs/i)
              sort_i    805.194 i/s -     810.000 times in 1.005969s (1.24ms/i)
              sort_s    25.315k i/s -     26.741k times in 1.056332s (39.50μs/i)
Calculating -------------------------------------
           sort_by_i     7.590k i/s -     23.307k times in 3.070740s (131.75μs/i)
           sort_by_s    12.333k i/s -     37.373k times in 3.030289s (81.08μs/i)
              sort_i    782.899 i/s -      2.415k times in 3.084688s (1.28ms/i)
              sort_s    25.393k i/s -     75.944k times in 2.990800s (39.38μs/i)

Comparison:
              sort_s:     25392.5 i/s 
           sort_by_s:     12333.1 i/s - 2.06x  slower
           sort_by_i:      7590.0 i/s - 3.35x  slower
              sort_i:       782.9 i/s - 32.43x  slower

こちらは1秒あたりの実行回数が出るようなので、数字が大きいほうが速いということになるらしい。
文字列のままsortする方が文字列のままsort_byするより2倍ほど速い結果になりました。

以上

0
0
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?