2011-02-05 8 views
34

私は、文字列があります。文字列の空白を削除するにはどうすればよいですか?

"のfoo(2つのスペース)バー(3つのスペース)baaar(6つのスペース)ザ・フー・コンスピラシー"

なしがあるはずですので、私はそれで繰り返しスペースを削除するにはどうすればよいの任意の2つの単語の間に複数のスペース?

+2

ご存知のように、この種の質問はすべてのStringメソッドを確認することで簡単に答えられます。 String、Array、およびEnumerableメソッドのドキュメントを熟知していることを強くお勧めします。 –

+0

どこから始めたらよいかわからない場合は、[http://ruby-doc.org/](http://ruby-doc.org/)]にアクセスし、[Core API](http: /ruby-doc.org/core)リンクをクリックしてから、最上部の列のStringクラスをクリックします。 – Phrogz

+0

OPの防御には、いくつかの方法でスペースを削除することができますが、特にベンチマークの結果を見るときは、そのすべてが最も直感的ではありません。 –

答えて

38
>> str = "foo bar bar  baaar" 
=> "foo bar bar  baaar" 
>> str.split.join(" ") 
=> "foo bar bar baaar" 
>> 
+3

+1それを行う面白い方法は、-1他のものと比較して非効率的な提案は、より適切な選択肢。 – Phrogz

+2

@Phrogz。非効率的な?それを証明するベンチマークはどれですか? – kurumi

+1

http://stackoverflow.com/questions/4907068/remove-repeated-spaces-in-ruby-string/4911709#4911709: – zetetic

7

正規表現を使用して、繰り返し空白(\s+)と一致し、スペースで置き換えます。あなただけの、スペースを置き換える/ +/代わりの/\s+/を使用したいと

"foo bar foobar".gsub(/\s+/, ' ') 
=> "foo bar foobar" 

これは、すべての空白文字と一致します。

"foo bar \nfoobar".gsub(/ +/, ' ') 
=> "foo bar \nfoobar" 
3

gsubと正規表現を使用してください。たとえば :

str = "foo bar bar  baaar" 
str.gsub(/\s+/, " ") 

新しい文字列を返しますか、直接gsub!を使用してSTR変更することができます。

BTW。正規表現は非常に便利です - あなたの正規表現をテストするためにインターネットにはたくさんのリソースがあります。例えば、rubular.comを試してみてください。

16

ActivesupportFacets両方がString#squish(それはまた、文字列内の改行を削除することに注意)を提供することに注意して、他の回答を補完する:方法

>> "foo bar bar  baaar".squish 
=> "foo bar bar baaar" 
+1

'#squish'は改行も削除することに注意してください。 – moveson

75
irb> "asd asd asd asd".squeeze(" ") 
=> "asd asd asd asd" 

String#squeeze

+2

真実ではありません...それは文字列を "ダメージ"する可能性があります。 "50b2a6cc6d5a2fb4e7000006"の場合は "50b2a6c6d5a2fb4e706"となります。 – xpepermint

+8

@xpepermint、 '" ''パラメータに注意してください。 – Nakilon

+0

ow ...私はそれを逃した、申し訳ありません:) – xpepermint

5

をパフォーマンスは向上しますか? zeteticの答え@から

$ ruby -v 
ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux] 

$ cat squeeze.rb 
require 'benchmark' 
include Benchmark 

string = "foo bar bar  baaar" 
n = 1_000_000 
bm(6) do |x| 
    x.report("gsub  ") { n.times { string.gsub(/\s+/, " ") } } 
    x.report("squeeze ") { n.times { string.squeeze } } 
    x.report("split/join") { n.times { string.split.join(" ") } } 
end 

$ ruby squeeze.rb 
      user  system  total  real 
gsub  4.970000 0.020000 4.990000 ( 5.624229) 
squeeze  0.600000 0.000000 0.600000 ( 0.677733) 
split/join 2.950000 0.020000 2.970000 ( 3.243022) 
+2

このベンチマークは正しくありません。 'string.squeeze =>" fo bar bar bar "は繰り返し文字をすべて取り除いています。 'string.squeeze( '')'に変更すると、 'gsub'と' split.join( '') 'の間に強固に置かれ、最後が最も速くなります。更新されたベンチマークコードについては私の答えをご覧ください。 –

23

更新ベンチマーク:

require 'benchmark' 
include Benchmark 

string = "foo bar bar  baaar" 
n = 1_000_000 
bm(12) do |x| 
    x.report("gsub  ") { n.times { string.gsub(/\s+/, " ") } } 
    x.report("squeeze(' ')") { n.times { string.squeeze(' ') } } 
    x.report("split/join") { n.times { string.split.join(" ") } } 
end 

二回、それを実行した後、私のデスクトップ上で実行した場合、これらの値になり:

ruby test.rb; ruby test.rb 
        user  system  total  real 
gsub   6.060000 0.000000 6.060000 ( 6.061435) 
squeeze(' ') 4.200000 0.010000 4.210000 ( 4.201619) 
split/join 3.620000 0.000000 3.620000 ( 3.614499) 
        user  system  total  real 
gsub   6.020000 0.000000 6.020000 ( 6.023391) 
squeeze(' ') 4.150000 0.010000 4.160000 ( 4.153204) 
split/join 3.590000 0.000000 3.590000 ( 3.587590) 

問題はsqueezeは、いずれかを削除するということです文字が繰り返され、異なる出力文字列が生成され、OPのニーズを満たしません。 squeeze(' ')はそのニーズを満たしていますが、操作が遅くなります。

string.squeeze 
=> "fo bar bar bar" 

私はsplit.joinがより速くなる可能性があり、それは大規模な文字列にまで開催するように、それはいないようでしたので、私は長い文字列を持っているでしょうどのような影響を参照してベンチマークを調整する方法について考えていた。

require 'benchmark' 
include Benchmark 

string = (["foo bar bar  baaar"] * 10_000).join 
puts "String length: #{ string.length } characters" 
n = 100 
bm(12) do |x| 
    x.report("gsub  ") { n.times { string.gsub(/\s+/, " ") } } 
    x.report("squeeze(' ')") { n.times { string.squeeze(' ') } } 
    x.report("split/join") { n.times { string.split.join(" ") } } 
end 

ruby test.rb ; ruby test.rb 

String length: 250000 characters 
        user  system  total  real 
gsub   2.570000 0.010000 2.580000 ( 2.576149) 
squeeze(' ') 0.140000 0.000000 0.140000 ( 0.150298) 
split/join 1.400000 0.010000 1.410000 ( 1.396078) 

String length: 250000 characters 
        user  system  total  real 
gsub   2.570000 0.010000 2.580000 ( 2.573802) 
squeeze(' ') 0.140000 0.000000 0.140000 ( 0.150384) 
split/join 1.400000 0.010000 1.410000 ( 1.397748) 

長い行は大きな違いをもたらします。


あなたはGSUB/\ sの{2、} /その後、GSUBを使用しない場合は、 '「)わずかに速いです。

実際はありません。あなたはスピードをしたい場合

require 'benchmark' 
include Benchmark 

string = "foo bar bar  baaar" 
puts string.gsub(/\s+/, " ") 
puts string.gsub(/\s{2,}/, ' ') 
puts string.gsub(/\s\s+/, " ") 

string = (["foo bar bar  baaar"] * 10_000).join 
puts "String length: #{ string.length } characters" 
n = 100 
bm(18) do |x| 
    x.report("gsub")    { n.times { string.gsub(/\s+/, " ") } } 
    x.report('gsub/\s{2,}/, "")') { n.times { string.gsub(/\s{2,}/, ' ') } } 
    x.report("gsub2")    { n.times { string.gsub(/\s\s+/, " ") } } 
end 
# >> foo bar bar baaar 
# >> foo bar bar baaar 
# >> foo bar bar baaar 
# >> String length: 250000 characters 
# >>       user  system  total  real 
# >> gsub     1.380000 0.010000 1.390000 ( 1.381276) 
# >> gsub/\s{2,}/, "") 1.590000 0.000000 1.590000 ( 1.609292) 
# >> gsub2    1.050000 0.010000 1.060000 ( 1.051005) 

は、gsub2を使用します。ここでは、ベンチマークのバージョンだけではアサーションをテストすることです。 squeeze(' ')はまだgsubの実装の周りに円を実行します。

+0

+1良いキャッチフル – zetetic

+0

@zetetic、私はベンチマークは不可欠なツールだと思う。私は、何かが特定のタスクを実行する最も速い方法であると仮定した回数を数えることはできず、ベンチマークが間違っていることを証明しました。私はこの目的のためにアプリで使っていましたが、「スプリット/ジョイン」を最速にすることは決して考えていませんでした。 –

+0

@zetetic、追加されたテスト結果をチェックしてください。 –

関連する問題