Ruby文字列のクリーンアップが13倍速く
考えをコードに変換するときは、ほとんどの場合、最もよく知っている方法を使用します。これらは頭に浮かぶ方法であり、自動的に表示されます。クリーンアップが必要な文字列が表示され、結果を得る方法を指で入力します。
多くの場合、自動的に入力するメソッドは、最も一般的なRubyメソッドです。これは、他のメソッドよりも読み取りと書き込みが多いためです。 #gsub
文字列内の文字を置き換える一般的な方法です。しかし、Rubyにはさらに多くの機能があり、標準的な操作のためのより専門的な便利な方法があります。
私はRubyの豊富なイディオムが大好きです。それは、コードがよりエレガントで読みやすくなるからです。この豊富さの恩恵を受けたい場合は、コードの最も単純な部分(文字列のクリーンアップなど)でもリファクタリングに時間を費やす必要があり、語彙を拡張するには少し手間がかかります。問題は、余分な努力はそれだけの価値があるのかということです。
スペースを削除する4つの方法
クレジットカード番号を表す文字列は次のとおりです:"055444285"。それを操作するには、スペースを削除します。 #gsub
これを行うことができます。 #gsub
を使用 何でもすべてに置き換えることができます。しかし、他のオプションがあります。
string = "055 444 285"
string.gsub(/ /, '')
string.gsub(' ', '')
string.tr(' ', '')
string.delete(' ')
# => "055444285"
便利な方法で一番好きな表現力です。最後のものはこれの良い例です:それは「スペースを削除する」より明白になりません。オプション間のトレードオフを考えると、もちろんパフォーマンスの問題が発生しない限り、読みやすさが私の最優先事項です。それでは、私のお気に入りのソリューションである#delete
がどれほど苦痛か見てみましょう。 本当に原因です。
上記の例をベンチマークしました。これらの方法のどれが最速だと思いますか?
Benchmark.ips do |x|
x.config(time: 30, warmup: 2)
x.report('gsub') { string.gsub(/ /, '') }
x.report('gsub, no regex') { string.gsub(' ', '') }
x.report('tr') { string.tr(' ','') }
x.report('delete') { string.delete(' ') }
x.compare!
end
パフォーマンスの高いものから低いものへの順序を推測します。トグルを開いて結果を確認します
Comparison:
delete: 2326817.5 i/s
tr: 2121629.8 i/s - 1.10x slower
gsub, no regex: 868184.1 i/s - 2.68x slower
gsub: 474970.5 i/s - 4.90x slower
注文については驚きませんでしたが、速度の違いには驚きました。 #gsub
速度が遅いだけでなく、リーダーが引数を「デコード」するために余分な労力が必要になります。単なるスペース以上のものをクリーンアップするときに、この比較がどのように機能するかを見てみましょう。
番号を選んでください
次の電話番号を使用してください:'(408) 974-2414'
。数字だけが必要だとしましょう=>4089742414
。 #scan
を追加しました また、不要なものをすべて削除しようとするのではなく、特定の目的を目指していることをより明確に表現しているのが好きだからです。
Benchmark.ips do |x|
x.config(time: 30, warmup: 2)
x.report ('gsub') { string.gsub(/[^0-9] /, '') }
x.report('tr') { string.tr("^0-9", "") }
x.report('delete_chars') { string.delete("^0-9") }
x.report('scan') { string.scan(/[0-9]/).join }
x.compare!
end
もう一度、順序を推測し、トグルを開いて答えを確認します
Comparison:
delete_chars: 2006750.8 i/s
tr: 1856429.0 i/s - 1.08x slower
gsub: 523174.7 i/s - 3.84x slower
scan: 227717.4 i/s - 8.81x slower
正規表現を使用すると処理が遅くなりますが、これは驚くべきことではありません。そして、#scan
の表現力を明らかにする意図 私たちに多大な費用がかかります。しかし、Rubyの特殊なメソッドがクリーンアップをどのように処理するかを見ると、もっと多くのことを味わうことができました。
お金について
部分文字列"€ "
を削除するいくつかの方法を試してみましょう 文字列から"€ 300"
。次のソリューションのいくつかは、正確な部分文字列"€ "
を指定します 、一部は単にすべての通貨記号またはすべての非数字を削除します。
Benchmark.ips do |x|
x.config(time: 30, warmup: 2)
x.report('delete specific chars') { string.delete("€ ") }
x.report('delete non-numericals') { string.delete("^0-9") }
x.report('delete prefix') { string.delete_prefix("€ ") }
x.report('delete prefix, strip') { string.delete_prefix("€").strip }
x.report('gsub') { string.gsub(/€ /, '') }
x.report('gsub-non-nums') { string.gsub(/[^0-9]/, '') }
x.report('tr') { string.tr("€ ", "") }
x.report('slice array') { string.chars.slice(2..-1).join }
x.report('split') { string.split.last }
x.report('scan nums') { string.scan(/\d/).join }
x.compare!
end
勝者は#delete
の1つであると期待できます。 s。しかし、#delete
のどれか バリアントが最速になると思いますか?プラス:他の方法の1つは、いくつかの#delete
よりも高速です s。どれ?
推測してから開きます。
Comparison:
delete prefix: 4236218.6 i/s
delete prefix, strip: 3116439.6 i/s - 1.36x slower
split: 2139602.2 i/s - 1.98x slower
delete non-numericals: 1949754.0 i/s - 2.17x slower
delete specific chars: 1045651.9 i/s - 4.05x slower
tr: 951352.0 i/s - 4.45x slower
slice array: 681196.2 i/s - 6.22x slower
gsub: 548588.3 i/s - 7.72x slower
gsub-non-nums: 489744.8 i/s - 8.65x slower
scan nums: 418978.8 i/s - 10.11x slower
配列をスライスすることでさえ、#gsub
よりも速いことに驚きました。 #split
の速さをいつも喜んでいます。 は。また、非数値をすべて削除する方が、特定の部分文字列を削除するよりも高速であることに注意してください。
お金を追いかける
番号の後の通貨を削除しましょう。 (遅い#gsub
をスキップしました バリアント。)
Benchmark.ips do |x|
x.config(time: 30, warmup: 2)
x.report('gsub') { string.gsub(/ USD/, '')
x.report('tr') { string.tr(" USD", "") }
x.report('delete_chars') { string.delete("^0-9")
x.report('delete_suffix') { string.delete_suffix(" USD") }
x.report('to_i.to_s') { string.to_i.to_s }
x.report("split") { string.split.first }
x.compare!
end
勝者の間には引き分けがあります。最速を目指して競争するのはどれだと思いますか?
そして:ここに`#gsub`がどれだけ遅いかを推測します。
Comparison:
delete_suffix: 4354205.4 i/s
to_i.to_s: 4307614.6 i/s - same-ish: difference falls within error
split: 2870187.8 i/s - 1.52x slower
delete_chars: 1989566.1 i/s - 2.19x slower
tr: 1853957.1 i/s - 2.35x slower
gsub: 524080.6 i/s - 13.22x slower
ニーズに合った特別な方法が常にあるとは限りません。 #to_i
は使用できません 先頭の「0」を維持する必要がある場合。そして#delete_suffix
通貨が米ドルであるという仮定に大きく依存しています。
特殊な方法は、特定のコンテキストでの特定のタスクに適した精密ツールのようなものです。したがって、#gsub
が常に発生する場合があります まさに私たちが必要としているものです。それは用途が広く、常に頭の中にあります。しかし、処理が少し難しくなる可能性があり、多くの場合、予想よりも遅くなります。私にとって、Rubyの豊かさは、一緒に仕事をするのがとても楽しい理由の1つでもあります。スピードウィンは素晴らしいボーナスです。
-
Ruby文字列のフォーマット
Rubyで文字列をフォーマットする方法について話しましょう。 なぜ文字列をフォーマットしたいのですか?数値が10未満であっても、先行ゼロを使用したり(例:01、02、03…)、コンソール出力を列に適切にフォーマットしたりすることができます。 他の言語では、 printfを使用できます 文字列をフォーマットする関数です。Cを使用したことがある場合は、おそらくそのことに精通しているでしょう。 printfを使用するには フォーマット指定子のリストと変数または値のリストを定義する必要があります。 Ruby文字列フォーマット入門 sprintf はRubyでも利用できます。この投稿では、よ
-
Javaで文字列を比較する方法
文字列が等しいかどうかを比較するには、Stringオブジェクトのequalsを使用する必要があります またはequalsIgnoreCase メソッド。 ==を使用すべきでない理由もわかります 文字列を比較する演算子。 文字列とequals()メソッドの比較 Javaで2つの文字列を比較する必要があり、文字列の大文字と小文字も気にする必要がある場合は、equals()を使用できます。 メソッド。 たとえば、次のスニペットは、文字列の2つのインスタンスが大文字小文字を含むすべての文字で等しいかどうかを判断します。 public class CompareTwoStrings { p