Ruby 一行中的多个就地替换

Ruby 一行中的多个就地替换,ruby,Ruby,当被替换的模式都不能保证匹配时,对字符串执行多个就地替换的最惯用方法是什么 例如,假设我有一个字符串数组,我想在每个字符串中用“快乐”替换“悲伤”,用“你好”替换“再见”: a = ["I am sad", "goodbye for now"] # This will work: a.map! do |s| s = s.gsub(/sad/,"happy").gsub(/goodbye/,"hello") end # So will this: a.each do |s| s.

当被替换的模式都不能保证匹配时,对字符串执行多个就地替换的最惯用方法是什么

例如,假设我有一个字符串数组,我想在每个字符串中用“快乐”替换“悲伤”,用“你好”替换“再见”:

a = ["I am sad", "goodbye for now"]

# This will work:
a.map! do |s|
    s = s.gsub(/sad/,"happy").gsub(/goodbye/,"hello")
end
# So will this:
a.each do |s|
    s.gsub!(/sad/,"happy")
    s.gsub!(/goodbye/,"hello")
end
# This will fail when s does not match /sad/:
a.each do |s|
    s.gsub!(/sad/,"happy").gsub!(/goodbye/,"hello")
end
第一个选项似乎有点傻,因为从逻辑上讲,我试图进行就地替换,而不是重新分配。第二种选择是可以的,但我的美感告诉我,要求将替代转换为两个连续的语句似乎是错误的,特别是在只有一个或另一个替代预期会成功的情况下(具有讽刺意味的是,正是这种情况导致了第三个版本,在我看来“正确”的版本失败). 另外,像我在这里这样破坏性地使用
每个
可能是错误的,但是如果我使用
映射
相反,我需要添加
s
作为块中的最后一行,以确保在替换失败时不会意外生成
nil
条目,这似乎比第一个选项更愚蠢

我在猜测
(g)sub的原因方法返回
nil
,因为这使它们便于在逻辑构造中使用,这是一个很好的理由(特别是因为非破坏性版本显然无论如何都必须返回“true”值)


所以…我知道这只不过是一个小小的美学争论,但是有没有比我所展示的两种(工作)方式更好的方法呢?如果没有,是否有任何理由选择其中一个而不是另一个(除了我对第二个版本的直观审美偏好)?

首先,您需要创建一个
替换\u hash
,如下所示:

replacement_hash = { "sad" => "happy", "goodbye" => "hello"}
a = ["I am sad", "goodbye for now"]
Regexp.union(replacement_hash.keys) # => /sad|goodbye/
a.map { |s| s.gsub(Regexp.union(replacement_hash.keys), replacement_hash) }
# => ["I am happy", "hello for now"]
如果需要就地更换,请执行以下操作:-

a.each { |s| s.gsub!(Regexp.union(replacement_hash.keys), replacement_hash) }

很好的解决方案。虽然从技术上讲,他需要就地更换,所以你可以更改
a.map。。s、 gsub
a.每个。。。s、 gsub@DaniëlKnippers谢谢。。请不要删除您的评论。。因为它很重要…-)。。。。呵呵。我没有意识到
(g)sub(!)
可以使用哈希值替换键。谢谢。不过有一些奇怪的地方:(1)为什么
(g)sub(!)
的单参数版本不检查它们的参数是散列还是模式?在提供散列时显式指定模式似乎是多余的,因为我可以想象,在大多数情况下,您希望该模式与此处相同,即,
Regexp.union(r\u hash.keys)
。对于
gsub!(r_hash)
返回枚举数对我来说没有什么意义。(2) 显然(至少在Ruby 2.0中),
replacement\u hash
的键必须是字符串而不是符号。知道为什么吗?