如何删除string中的重复空格?

我有一个string:

“foo(2个空格)bar(3个空格)baaar(6个空格)fooo”

我如何去除其中的重复空间,所以在任何两个单词之间不应该有一个以上的空格?

>> str = "foo bar bar baaar" => "foo bar bar baaar" >> str.split.join(" ") => "foo bar bar baaar" >> 
 irb> "asd asd asd asd".squeeze(" ") => "asd asd asd asd" 

串#挤

@ zetetic的答案更新了基准:

 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删除任何重复的字符,这会导致不同的输出string,不符合OP的需要。 squeeze(' ')确实符合需要,但放慢其运作。

 string.squeeze => "fo bar bar bar" 

我正在考虑split.join怎么会更快,而且看起来好像没有大string,于是我调整了基准,看看长string会产生什么效果:

 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,那么gsub / \ s {2,} /,'')稍快。

不是真的。 以下是testing这个断言的基准testing版本:

 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实现运行。

为了补充其他答案(纯Ruby片段),请注意, Activesupport和Facets都提供了String# squish :

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

使用正则expression式来匹配重复的空格(\s+)并将其replace为空格。

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

这匹配每个空格,因为您只想replace空格,请使用/ +/而不是/\s+/

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

哪种方法更好?

 $ 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) 

只要使用gsub和regexp。 例如:

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

将返回新的string,或者你可以直接使用gsub!修改str gsub!

BTW。 正则expression式非常有用 – 互联网上有大量资源,用于testing自己的正则expression式 ,例如rubular.com 。