2010-07-08 2 views
3

Если у меня есть строка, как так ..Regex поп-викторина дня: D

There     is    a lot   of   white space. 

И я хочу, чтобы удалить все нежелательные места в регулярном выражении Руби .. Как определить белое пространство и удалить его так что между всеми словами будет по крайней мере одно пробел?

До сих пор у меня есть:

gsub(/\s{2,}/, '') 

Но как вы можете видеть, что сворачивает несколько слов друг в друга.

ответ

11

Вы близко. После обрезки пробелов слева и справа,

str.strip.gsub(/\s{2,}/, ' ') 

заменить любые наборы нескольких пространств одним пробелом. Это, конечно, предполагает, что вы имеете дело только с реальными пространствами.

+0

О, мужчина! : D так близко !!! – Trip

+0

Этот ответ работает. Он явно превосходит тривиальный 's.gsub (/ \ s + /, '')'. –

+0

@Steven Xu - хотя замена одного пространства одним пространством тоже может быть забавой! – Matchu

2

Назад, когда я писал Perl-код все время, я использовал для регулярного выражения для строковых манипуляций. Затем, в один прекрасный день, я захотел сделать код, который искал и разбирал содержимое строки, и написал тест, чтобы сравнить некоторые регулярные и стандартные поисковые запросы по индексу. Поиск по индексу отменил регулярное выражение. Это не так сложно, но иногда нам не нужны сложные решения простых проблем.

Вместо того, чтобы мгновенно захватить регулярное выражение, String.squeeze(' ') может обрабатывать сжатие повторяющихся пространств намного быстрее. Рассмотрим вывод теста:

 
#!/usr/bin/env ruby 

require 'benchmark' 

asdf = 'There     is    a lot   of   white space.' 

asdf.squeeze(' ') # => "There is a lot of white space." 
asdf.gsub(/ +/, ' ') # => "There is a lot of white space." 
asdf.gsub(/ {2,}/, ' ') # => "There is a lot of white space." 
asdf.gsub(/\s\s+/, ' ') # => "There is a lot of white space." 
asdf.gsub(/\s{2,}/, ' ') # => "There is a lot of white space." 

n = 500000 
Benchmark.bm(8) do |x| 
    x.report('squeeze:') { n.times{ asdf.squeeze(' ') } } 
    x.report('gsub1:') { n.times{ asdf.gsub(/ +/, ' ') } } 
    x.report('gsub2:') { n.times{ asdf.gsub(/ {2,}/, ' ') } } 
    x.report('gsub3:') { n.times{ asdf.gsub(/\s\s+/, ' ') } } 
    x.report('gsub4:') { n.times{ asdf.gsub(/\s{2,}/, ' ') } } 
end 

puts 
puts "long strings" 
n  = 1000 
str_x = 1000 
Benchmark.bm(8) do |x| 
    x.report('squeeze:') { n.times{(asdf * str_x).squeeze(' ') }} 
    x.report('gsub1:') { n.times{(asdf * str_x).gsub(/ +/, ' ') }} 
    x.report('gsub2:') { n.times{(asdf * str_x).gsub(/ {2,}/, ' ') }} 
    x.report('gsub3:') { n.times{(asdf * str_x).gsub(/\s\s+/, ' ') }} 
    x.report('gsub4:') { n.times{(asdf * str_x).gsub(/\s{2,}/, ' ') }} 
end 
# >>    user  system  total  real 
# >> squeeze: 1.050000 0.000000 1.050000 ( 1.055833) 
# >> gsub1: 3.700000 0.020000 3.720000 ( 3.731957) 
# >> gsub2: 3.960000 0.010000 3.970000 ( 3.980328) 
# >> gsub3: 4.520000 0.020000 4.540000 ( 4.549919) 
# >> gsub4: 4.840000 0.010000 4.850000 ( 4.860474) 
# >> 
# >> long strings 
# >>    user  system  total  real 
# >> squeeze: 0.310000 0.180000 0.490000 ( 0.485224) 
# >> gsub1: 3.420000 0.130000 3.550000 ( 3.554505) 
# >> gsub2: 3.850000 0.120000 3.970000 ( 3.974213) 
# >> gsub3: 4.880000 0.130000 5.010000 ( 5.015750) 
# >> gsub4: 5.310000 0.150000 5.460000 ( 5.461797) 

тесты основаны на сдачу в аренду squeeze(' ') или gsub() полосы дублируется пространства. Как я и ожидал, сжатие ('') сдувает регулярное выражение. Регулярное выражение с использованием символа пробега быстрее, чем эквивалентный шаблон с использованием \s.

Конечно, регулярное выражение более гибкое, но, думая о том, требуется ли регулярное выражение, может иметь большое значение в скорости обработки вашего кода.

Смежные вопросы