2016-03-22 6 views
2

Ich bin auf der Suche nach einer Möglichkeit, Wörter und Phrasen in einer Zeichenfolge aus einem Hash zu ersetzen. Ich weiß, dass dies elegant in Ruby getan werden kann> 1,9 für einzelne Worte:Unterwörter (und Phrasen) in Zeichenfolge aus Hash

a = "every good boy does fine" 
h = {"every" => "all","boy" => "girl", "fine" =>"well" } 
a.gsub(/\w+/) { |m| h.fetch(m,m)} 

https://stackoverflow.com/a/20650800/4530434

Dies gilt jedoch nicht funktionieren, wenn der Satz, den ich ersetzt will mehr als ein Wort ist. Was ich will, ist etwas wie das, im Idealfall mit beliebig langen String-Substitutionen arbeiten, aber ich würde mit zwei (oder drei) Wortphrasen zufrieden sein.

a = "I love the eighteen nineties" 
b = {"eighteen nineties" => "1890's" } 
# => "I love the 1890's" 

Ich habe oben mit dem Regexp im Code versucht, das Hantieren, kann aber nicht bekommen anythig zu arbeiten.

+0

ich getan habe einige untersuchen, und es scheint, wäre es Es ist unmöglich, eine Regex zu erstellen, die alle möglichen Kombinationen aufeinanderfolgender Wörter auswählt, da es nach einer Übereinstimmung unmöglich ist, diese Übereinstimmung in einem anderen Spiel wiederzuverwenden. dh es gibt keine Regex, die die Matches für "großen bösen Wolf" als "großen bösen" & "bösen Wolf" finden würden. (Dun Dun Dun) – 4castle

+0

Ich hätte klarer sein sollen. Was ich mit "Phrasen" meinte, sind aufeinanderfolgende Wörter. Ich brauche nicht alle Kombinationen. – sarkon

+0

Sicher, aber ich sage, dass es keine Möglichkeit gibt, zwei Wörter auf die gleiche Weise wie ein Wort zu vergleichen. Es gibt keine Regex, die Sie einfach in den verwendeten Code einfügen können, um das Problem zu lösen. Sie müssen die Regex anders verwenden. Ich versuche nur die Antworten zu verallgemeinern, die diese Frage haben wird. Das ist eine sehr gute Frage. – 4castle

Antwort

1

ein Muster Stellen auf der Grundlage der Zuordnung:

text = "I love the eighteen nineties" 
mapping = {"eighteen nineties" => "1890's"} 
pattern = /\b#{Regexp.union(mapping.keys)}\b/ 
text.gsub(pattern, mapping) 
# => "I love the 1890's" 
+1

Es scheint wie '/\b#{Regexp.union (map.keys)} \ b /' ist viel sauberer und macht das gleiche. –

+0

@ Jordan, Danke. Ich habe die Antwort entsprechend Ihrem Vorschlag aktualisiert. – falsetru

+1

Sie können den Hash auch als zweites Argument an 'gsub' übergeben. –

0

Haben Sie daran gedacht? Beachten Sie, dass gsub! destruktiv ist und die Zeichenkette dauerhaft in a ersetzen wird. Dies durchläuft jeden Hash-Schlüssel, und wo der Hash-Schlüssel in a gefunden wird, wird er durch den Wert ersetzt, der im Hash relativ zum Schlüssel gespeichert ist.

irb(main):001:0> a = "I love the eighteen nineties" 
=> "I love the eighteen nineties" 
irb(main):002:0> b = {"eighteen nineties" => "1890's" } 
=> {"eighteen nineties"=>"1890's"} 
irb(main):003:0> b.keys.each { |k| a.gsub!(k, b[k]) } 
=> ["eighteen nineties"] 
irb(main):004:0> a 
=> "I love the 1890's" 
1

Versuchen Sie, durch jeden Wert in der Hash-Iteration:

>> a = "I love the eighteen nineties" 
>> b = {"eighteen nineties" => "1890's", "love" => "enjoy" } 

>> b.inject(a) {|s, (k, v)| s.gsub(k, v)} 
=> "I enjoy the 1890's" 
Verwandte Themen