Regex поп-викторина дня: D - PullRequest
3 голосов
/ 08 июля 2010

Если у меня есть такая строка ..

 There                   is             a lot           of           white space.

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

Пока у меня есть:

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

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

Ответы [ 2 ]

11 голосов
/ 08 июля 2010

Ты рядом. После обрезки пробелов слева и справа,

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

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

2 голосов
/ 09 июля 2010

Когда я все время писал код на 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.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...