2011-02-05 68 views
34

我有一個字符串:如何刪除字符串中的重複空格?

「FOO(2位)巴(3位)baaar(6位)fooo」

如何刪除重複的空間在裏面,所以應該沒有任何兩個單詞之間有多於一個空格?

+2

您知道,通過查看所有String方法可以輕鬆解決這類問題。我強烈建議熟悉String,Array和Enumerable方法的文檔。 – 2011-02-05 15:41:29

+0

如果您不知道從哪裏開始,請訪問[http://ruby-doc.org/](http://ruby-doc.org/),然後單擊[Core API](http:///ruby-doc.org/core)鏈接,然後單擊頂部中間列中的String類。 – Phrogz 2011-02-05 15:51:01

+0

對於OP的防守,刪除空格可以通過多種方式完成,但並非所有方法都是最直觀的,特別是當您查看基準測試結果時。 – 2011-12-30 19:19:37

回答

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

使用正則表達式來匹配重複的空格(\s+)並將其替換爲空格。

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

這每一個空格相匹配,因爲你只需要更換空間,使用/ +/代替/\s+/

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

只需使用gsub和正則表達式。 例如:

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

將返回新的字符串,也可以直接STR使用gsub!修改。

順便說一句。正則表達式非常有用 - 互聯網上有大量資源,例如用於測試自己的正則表達式嘗試rubular.com

16

爲了配合其他的答案,注意,這兩個ActivesupportFacets提供String#squish(請注意,它還會刪除字符串中的新行):

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

請記住`#squish`也會刪除換行符。 – moveson 2017-01-13 21:03:34

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

String#squeeze

+2

不是真的......它可以「損害」字符串...例如將是「50b2a6cc6d5a2fb4e7000006」,你會得到「50b2a6c6d5a2fb4e706」。 – xpepermint 2012-11-27 20:33:01

+8

@xpepermint,注意``「``參數。 – Nakilon 2012-11-28 12:24:38

5

哪種方法表現更好?

$ 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) 
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然後GSUB/\ s {2} /,'「)稍快。

不是。這裏的基準程序的版本來測試只是斷言:

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) 

如果你想要的速度,使用gsub2squeeze(' ')仍然會圍繞gsub實施運行。