web-dev-qa-db-fra.com

Ruby remplacement de chaînes multiples

str = "Hello☺ World☹"

La sortie attendue est:

"Hello:) World:("

Je peux le faire: str.gsub("☺", ":)").gsub("☹", ":(")

Existe-t-il un autre moyen pour que je puisse le faire en un seul appel de fonction?. Quelque chose comme:

str.gsub(['s1', 's2'], ['r1', 'r2'])
65
Sayuj

Depuis Ruby 1.9.2, String#gsub accepte le hachage comme deuxième paramètre pour le remplacement par des clés correspondantes. Vous pouvez utiliser une expression régulière pour faire correspondre la sous-chaîne qui doit être remplacée et passer le hachage pour les valeurs à remplacer.

Comme ça:

'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*')    #=> "h3ll*"
'(0) 123-123.123'.gsub(/[()-,. ]/, '')    #=> "0123123123"

Dans Ruby 1.8.7, vous obtiendriez la même chose avec un bloc:

dict = { 'e' => 3, 'o' => '*' }
'hello'.gsub /[eo]/ do |match|
   dict[match.to_s]
 end #=> "h3ll*"
109
Naren Sisodiya

Configurer une table de mappage:

map = {'☺' => ':)', '☹' => ':(' }

Ensuite, construisez une expression régulière:

re = Regexp.new(map.keys.map { |x| Regexp.escape(x) }.join('|'))

Et enfin, gsub :

s = str.gsub(re, map)

Si vous êtes coincé dans un terrain de 1,8, alors:

s = str.gsub(re) { |m| map[m] }

Vous avez besoin du Regexp.escape là au cas où tout ce que vous voulez remplacer a une signification particulière dans une expression régulière. Ou, grâce à steenslag, vous pouvez utiliser:

re = Regexp.union(map.keys)

et le devis sera pris en charge pour vous.

36
mu is too short

Vous pouvez faire quelque chose comme ça:

replacements = [ ["☺", ":)"], ["☹", ":("] ]
replacements.each {|replacement| str.gsub!(replacement[0], replacement[1])}

Il peut y avoir une solution plus efficace, mais cela rend au moins le code un peu plus propre

35
Nathan Manousos

Tard dans la soirée, mais si vous souhaitez remplacer certains caractères par un, vous pouvez utiliser une expression régulière

string_to_replace.gsub(/_|,| /, '-')

Dans cet exemple, gsub remplace les traits de soulignement (_), les virgules (,) ou () par un tiret (-)

18
lsaffie

Vous pouvez également utiliser tr pour remplacer plusieurs caractères dans une chaîne à la fois,

Par exemple, remplacer "h" par "m" et "l" par "t"

"hello".tr("hl", "mt")
 => "metto"

semble simple, soigné et plus rapide (pas beaucoup de différence cependant) que gsub

puts Benchmark.measure {"hello".tr("hl", "mt") }
  0.000000   0.000000   0.000000 (  0.000007)

puts Benchmark.measure{"hello".gsub(/[hl]/, 'h' => 'm', 'l' => 't') }
  0.000000   0.000000   0.000000 (  0.000021)
4
YasirAzgar

Un autre moyen simple et pourtant facile à lire est le suivant:

str = '12 ene 2013'
map = {'ene' => 'jan', 'abr'=>'apr', 'dic'=>'dec'}
map.each {|k,v| str.sub!(k,v)}
puts str # '12 jan 2013'
4
Diego Dorado

Riffing sur réponse de naren ci-dessus , j'irais avec

tr = {'a' => '1', 'b' => '2', 'z' => '26'}
mystring.gsub(/[#{tr.keys}]/, tr)

Donc 'zebraazzeebra'.gsub(/[#{tr.keys}]/, tr) renvoie "26e2r112626ee2r1"

1
gitb