2010-07-08 4 views
3

Si j'ai une chaîne comme si ..Regex quiz du jour: D

There     is    a lot   of   white space. 

Et je veux enlever tout l'espace indésirable dans regex Ruby .. Comment identifier un espace blanc et retirez-le de sorte qu'il y aura toujours au moins un espace blanc entre tous les mots?

Jusqu'à présent, j'ai:

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

Mais comme vous pouvez voir que plusieurs effondrements mots les uns aux autres.

Répondre

11

Vous êtes proche. Après avoir réduit les espaces de gauche et de droite,

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

remplacez tous les ensembles d'espaces multiples par un seul espace. Ceci, bien sûr, suppose que vous ne traitez que des espaces réels.

+0

Oh mec! : D si proche !!! – Trip

+0

Cette réponse fonctionne. Il est clairement supérieur au trivial 's.gsub (/ \ s + /, '')'. –

+0

@Steven Xu - bien que remplacer un seul espace avec un seul espace peut être amusant, aussi! – Matchu

2

Lorsque j'écrivais du code Perl tout le temps, j'utilisais des expressions régulières pour mes manipulations de chaînes. Puis, un jour, j'ai voulu faire du code qui cherchait et analysait le contenu des chaînes, et j'ai écrit un benchmark pour comparer certaines recherches indexées sur les regex et les chaînes standard. La recherche par index a balayé regex. Ce n'est pas aussi sophistiqué, mais parfois nous n'avons pas besoin de sophistication quand nous traitons de problèmes simples.

Plutôt que de saisir instantanément une regex, un String.squeeze(' ') peut gérer la compression des espaces répétés beaucoup plus rapidement. Pensez à la sortie de référence:

 
#!/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) 

Les tests sont basés sur dépouillent laisser squeeze(' ') ou gsub() les espaces en double. Comme je m'y attendais, squeeze ('') chasse l'expression régulière. Regex utilisant un caractère espace est plus rapide que le modèle équivalent en utilisant \s.

Bien sûr, les regex sont plus flexibles mais si vous avez besoin d'une regex, cela peut faire une grande différence dans la vitesse de traitement de votre code.