从散列中字符串中的子单词(和短语)

时间:2021-02-27 01:34:58

I'm looking for a way to substitute words and phrases in a string from a hash. I know that this can be done elegantly in Ruby > 1.9 for single words:

我正在寻找一种方法来从散列中替换字符串中的单词和短语。我知道这可以用Ruby > 1.9优雅地完成:

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

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

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

However this doesn't work if the phrase I want substituted is more than one word. What I want is something like this, ideally working with arbitrarily long string substitutions, but I'd settle for two (or three) word phrases.

但是,如果我想要替换的短语不止一个的话,这就行不通了。我想要的是这样的东西,理想的情况是使用任意长的字符串替换,但我只能使用两个(或三个)单词短语。

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

I've tried fiddling with the Regexp in the code above, but couldn't get anythig to work.

我试过在上面的代码中修改Regexp,但是没有找到任何方法。

3 个解决方案

#1


1  

Make a pattern based on the mapping:

基于映射制作模式:

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"

#2


1  

Try iterating through each value in in the hash:

尝试遍历散列中的每个值:

>> 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"

#3


0  

Is this what you had in mind? Note that gsub! is destructive and will permanently replace the string in a. This loops through each hash key, and where the hash key is found in a, it will replace it with the value stored in the hash relative to the key.

这就是你想要的吗?请注意,gsub !这个循环遍历每个散列键,在a中找到散列键的地方,它将用存储在散列中的相对于键的值替换它。

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


1  

Make a pattern based on the mapping:

基于映射制作模式:

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"

#2


1  

Try iterating through each value in in the hash:

尝试遍历散列中的每个值:

>> 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"

#3


0  

Is this what you had in mind? Note that gsub! is destructive and will permanently replace the string in a. This loops through each hash key, and where the hash key is found in a, it will replace it with the value stored in the hash relative to the key.

这就是你想要的吗?请注意,gsub !这个循环遍历每个散列键,在a中找到散列键的地方,它将用存储在散列中的相对于键的值替换它。

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"