2013-07-14 7 views
27
things = "one thing, two things, three things, four things" 

文字列をカンマで区切って、その周囲の空白をトリミングするにはどうすればよいですか?その結果:これは私はそれはそれはカンマで分割したときに最後の空白/大手の除去を除いて、何をしたいのかのほとんどを行いRuby:分割して、前後の空白を削除しますか?

things = things.to_s.tr("\n\t", "").strip.split(/,/) 

things = ["one thing", "two things", "three things", "four things"] 

現在、私はこれを持っています。これを達成する最良の方法は何ですか?上記の結果を別の配列に代入して、それを反復するのではなく、この式の一部としてやりたいと思います。これは答えとして意図されていない

"one thing, two things, three things, four things".split /\s*,\s*/ 
# => ["one thing", "two things", "three things", "four things"] 
+0

文字列「あるもの、2つのもの、3つのもの、4つのもの」と '{things things => things.to_s.tr(" \ n \ t "、" ").strip.split(/、/)}'?あなたが持っているものを正確にコピーしないでください。あなた以外の人々が理解できる質問にしてください。無関係なものを削除する。 – sawa

+0

OK、私はそれをしました。 :-) – Ben

答えて

63
s = "one thing, two things, three things, four things" 
s.split(",").map(&:strip) 
# => ["one thing", "two things", "three things", "four things"] 

ベンチマークコードを共有して、2つの提案されたソリューションをチェックできるようにしたかったのです自分自身:次の出力を生成し、私のシステム(OS X 10.8上のRuby 2.0.0p247)で

require 'benchmark' 

s = "one thing, two things, three things, four things" 
result = "" 

Benchmark.bmbm do |b| 
    b.report("strip/split: ") { 1_000_000.times {result = s.split(",").map(&:strip)} } 
    b.report("regex: ") { 1_000_000.times {result = s.split(/\s*,\s*/)} } 
end 

Rehearsal ------------------------------------------------- 
strip/split: 2.140000 0.000000 2.140000 ( 2.143905) 
regex:   3.570000 0.010000 3.580000 ( 3.572911) 
---------------------------------------- total: 5.720000sec 

        user  system  total  real 
strip/split: 2.150000 0.000000 2.150000 ( 2.146948) 
regex:   3.580000 0.010000 3.590000 ( 3.590646) 

これらの結果は、当然のことながら、ルビーのバージョンとの間で変化することが期待でき、ハードウェア、およびOSに依存します。

+2

パーフェクト。どうもありがとう! – Ben

+1

このソリューションは私の正規表現ベースのものより約2倍遅いことに注意してください。 – Koraktor

+1

@Koraktor実際にタイムアウトしましたか? Rubyが私を驚かせることもあります。 – pjs

6

#splitのための正規表現を使用してくださいを使用して、私ののUbuntu 13.04 OSでは、

2

ルビー2.0.0p0

require 'benchmark' 

s = "one thing, two things, three things, four things" 
result = "" 

Benchmark.bmbm do |b| 
    b.report("strip/split: ") { 1_000_000.times {result = s.split(",").map(&:strip)} } 
    b.report("regex: ") { 1_000_000.times {result = s.split(/\s*,\s*/)} } 
end 

Rehearsal ------------------------------------------------- 
strip/split: 6.260000 0.000000 6.260000 ( 6.276583) 
regex:   7.310000 0.000000 7.310000 ( 7.320001) 
--------------------------------------- total: 13.570000sec 

        user  system  total  real 
strip/split: 6.350000 0.000000 6.350000 ( 6.363127) 
regex:   7.290000 0.000000 7.290000 ( 7.302163) 
+0

*ベンチマーク*レポートを表示するための+ 1 *。 –

3

死んだ馬を打ち負かすことはできませんが、私にとって今や第2の性質になった2つの変更を加えることで、これをもう少しスピードアップすることができます。最初は、mapの代わりにmap!を使用して、分割配列のコピーを作成しないようにします。もう1つは、シンボルをproc構文で使用しないようにすることです(例:&:split、より冗長な構文で回避できる余分な操作が追加されます) 。

ベンチマークは、次のとおりです。

require 'benchmark' 

s = "one thing, two things, three things, four things" 
result = "" 

Benchmark.bmbm do |b| 
    b.report("strip/split (map/to_proc): ") { 1_000_000.times { result = s.split(",").map(&:strip) } } 
    b.report("strip/split (map): ") { 1_000_000.times { result = s.split(",").map { |e| e.strip } } } 
    b.report("strip/split (map!/to_proc): ") { 1_000_000.times { result = s.split(",").map!(&:strip) } } 
    b.report("strip/split (map!): ") { 1_000_000.times { result = s.split(",").map! { |e| e.strip } } } 
    b.report("regex: ") { 1_000_000.times { result = s.split(/\s*,\s*/) } } 
end 

結果:

        user  system  total  real 
strip/split (map/to_proc):  5.230000 0.010000 5.240000 ( 5.283079) 
strip/split (map):    4.660000 0.010000 4.670000 ( 4.716920) 
strip/split (map!/to_proc): 4.440000 0.020000 4.460000 ( 4.492943) 
strip/split (map!):   4.320000 0.010000 4.330000 ( 4.365386) 
regex:       7.190000 0.060000 7.250000 ( 7.322932) 

は、他の回答で提供ベンチマークと比較し、相互に相対的な数を読み取ることではない覚えておいてください。

+0

答えをくれてありがとう、面白いのは、より控えめな構文を見てみると面白いです。 :-) – Ben

+0

@Ben私の喜び。 Terserは通常より多くの "魔法"と同じであり、より多くの魔法はより多くの術を意味し、より多くの術は低速のパフォーマンスを意味します:) – xentek

6

私はベンチマークが大好きです...しかし、コードに含まれる100万個のループの中でこの操作をしない限り、速度の違いはわかりません。

したがって、最も良い解決策はおそらく最も明瞭な解決策です。アラップRakshitから多分これ1:

s = "one thing, two things, three things, four things" 
s.split(",").map!(&:strip) 
+2

あなたの解決策はまさに私のものと同じです.. * dup * –

+0

私はあなたが書いたものを読まなかったと思います。 "ベストソリューションはおそらく最も明瞭なものです..." 私のコメントはあなたの*ソリューション(または*任意の*特定のソリューション)についてではなく、スピード対スピード透明性/シンプルさ。言い換えれば、あなたの実際の状況がこのコードの最適化を要求しない限り、より高速であれば誰が気にします。独自の早期最適化は、しばしば技術的負債を増やすためのレシピです。 –

+0

私は*ベンチマーク*をそこに置いています。ベンチマークレポートから、どれが速いのかは明らかです。 :-) –

1

私は間違っていない場合は

things.split(", ") 

は、最も簡単な解決策になります。ただし、スペース文字が1つしかない場合にのみ機能します。 (カンマの後にスペースがあることに注意してください)

関連する問題