我正在尝试显示子串替换的所有可能选项。例如,如果我有这个字符串:
my_string = “yellow dogs are cooler than brown cats”
以下是可以替换的不同选项:
substitutions = {“yellow” => “black”, “brown” => “grey”}
我如何获得以下输出?
["black dogs are cooler than brown cats", "black dogs are cooler than grey cats", "yellow dogs are cooler than brown cats", "yellow dogs are cooler than grey cats"]
到目前为止,我只是拥有它,正如您所看到的,它没有得到所有选项:
substitutions.each do |key, value|
puts my_string.sub(key, value) if my_string.include? key
end
答案 0 :(得分:1)
你真正需要的是打开这个
substitutions = {“yellow” => “black”, “brown” => “grey”}
进入这个:
[{"yellow"=>"yellow", "brown"=>"brown"},
{"yellow"=>"yellow", "brown"=>"grey"},
{"yellow"=>"black", "brown"=>"brown"},
{"yellow"=>"black", "brown"=>"grey"}]
然后你可以简单地循环上面的内容并获得你想要的输出(你最初省略了身份转换,但最简单的是包含它)。以下是将substitutions
更改为:
substitutions.to_a[0].product(substitutions.to_a[1]).map do |ary|
Hash[substitutions.keys.zip ary]
end
然后它很简单:
_.each do |h|
p my_string.split.map {|word| h.fetch(word,word) }.join(' ')
end
"yellow dogs are cooler than brown cats"
"yellow dogs are cooler than grey cats"
"black dogs are cooler than brown cats"
"black dogs are cooler than grey cats"
这里我选择了拆分 - > sub each words - >重新加入全球sub
操作,因为你可能想要取代“棕色”而不是“布朗尼”。另一方面,这不能非常优雅地处理标点符号,因此您可以选择执行sub
或更复杂的正则表达式操作。由你决定。
答案 1 :(得分:1)
这是一个适用于任意数量的替换(不仅仅是两个)的通用解决方案:
my_string = "yellow dogs are cooler than brown cats"
substitutions = {"yellow"=>"black", "brown"=>"grey", "cooler"=>"sweeter"}
keys = substitutions.keys #=> ["yellow","brown","cooler"]
regx = /\b#{Regexp.union(keys)}\b/ #=> /\b(?:yellow|brown|cooler)\b/
axes = substitutions.to_a #=> [["yellow", "black"], ["brown", "grey"], ["cooler", "sweeter"]]
maps = axes.shift.product(*axes).map{ |*vals| Hash[ keys.zip(*vals) ] }
maps.each{ |map| p map, my_string.gsub(regx){ |match| map[match] } }
#=> {"yellow"=>"yellow", "brown"=>"brown", "cooler"=>"cooler"}
#=> "yellow dogs are cooler than brown cats"
#=> {"yellow"=>"yellow", "brown"=>"brown", "cooler"=>"sweeter"}
#=> "yellow dogs are sweeter than brown cats"
#=> {"yellow"=>"yellow", "brown"=>"grey", "cooler"=>"cooler"}
#=> "yellow dogs are cooler than grey cats"
#=> {"yellow"=>"yellow", "brown"=>"grey", "cooler"=>"sweeter"}
#=> "yellow dogs are sweeter than grey cats"
#=> {"yellow"=>"black", "brown"=>"brown", "cooler"=>"cooler"}
#=> "black dogs are cooler than brown cats"
#=> {"yellow"=>"black", "brown"=>"brown", "cooler"=>"sweeter"}
#=> "black dogs are sweeter than brown cats"
#=> {"yellow"=>"black", "brown"=>"grey", "cooler"=>"cooler"}
#=> "black dogs are cooler than grey cats"
#=> {"yellow"=>"black", "brown"=>"grey", "cooler"=>"sweeter"}
#=> "black dogs are sweeter than grey cats"
此处的关键是product
调用,将[[1,2],[3,4],[5,6]]
转换为:
[[1, 3, 5],
[1, 3, 6],
[1, 4, 5],
[1, 4, 6],
[2, 3, 5],
[2, 3, 6],
[2, 4, 5],
[2, 4, 6]]
换句话说,调用数组和传入的所有数组的所有组合。
使用带有gsub
的正则表达式可以提高效率,为每个完整的替换集合执行一次字符串传递。 gsub
的块形式产生找到的文本,然后用于查找所需的替换(有时与原始字符串相同)。
答案 2 :(得分:0)
my_string = "yellow dogs are cooler than brown cats"
substitutions = {"yellow" => "black", "brown" => "grey"}
substitutions.each do |k,v|
if my_string.include?(k)
my_string.sub! k, v
end
end
puts my_string
输出:黑狗比灰猫更酷
答案 3 :(得分:0)
另一种方式:
my_array = my_string.split.map(&:strip)
substitutions.to_a
.repeated_permutation(subs.size)
.map { |a| Hash[a.uniq] }
.uniq
.map { |h| my_array.map { |w| h.key?(w) ? h[w] : w }.join(' ') }
.concat([my_string])
.uniq
在失去一些效率的情况下,uniq
的前两次出现中的任何一个或两个都可以省略。
步骤:
my_string = "yellow dogs are cooler than brown cats"
substitutions = {"yellow"=>"black", "brown"=>"grey", "cooler"=>"neater"}
a = substitutions.to_a # 27 elements
#=> [["yellow", "black"], ["brown", "grey"], ["cooler", "neater"]]
b = a.repeated_permutation(subs.size)
#=> => #<Enumerator: [["yellow", "black"],...
b.to_a
#=> [[["yellow", "black"], ["yellow", "black"], ["yellow", "black"]],
# [["yellow", "black"], ["yellow", "black"], ["brown", "grey"]],
# [["yellow", "black"], ["yellow", "black"], ["cooler", "neater"]],
# [["yellow", "black"], ["brown", "grey"], ["yellow", "black"]],
# ...
# [["cooler", "neater"], ["cooler", "neater"], ["cooler", "neater"]]]
c = b.map {|a| Hash[a.uniq]} # 27 elements
#=> [{"yellow"=>"black"},
# {"brown"=>"grey", "yellow"=>"black"},
# {"cooler"=>"neater", "yellow"=>"black"},
# {"brown"=>"grey", "yellow"=>"black"},
# {"brown"=>"grey", "yellow"=>"black"},
# ...
# {"brown"=>"grey", "cooler"=>"neater", "yellow"=>"black"},
# ...
# {"cooler"=>"neater"}]
d = c.uniq
#=> [{"yellow"=>"black"},
# {"brown"=>"grey", "yellow"=>"black"},
# {"cooler"=>"neater", "yellow"=>"black"},
# {"brown"=>"grey", "cooler"=>"neater", "yellow"=>"black"},
# {"brown"=>"grey"},
# {"brown"=>"grey", "cooler"=>"neater"},
# {"cooler"=>"neater"}]
e = d.map {|h| my_array.map { |w| h.key?(w) ? h[w] : w }.join(' ') }
.concat([my_string])
#=> ["black dogs are cooler than brown cats",
# "black dogs are cooler than grey cats",
# "black dogs are neater than brown cats",
# "black dogs are neater than grey cats",
# "yellow dogs are cooler than grey cats",
# "yellow dogs are neater than grey cats",
# "yellow dogs are neater than brown cats",
# "yellow dogs are cooler than brown cats"]
e.uniq
# No effect here. Only relevant for substitutions such as
# "black=>"yellow" and "grey=>yellow", or "black"=>"black"
答案 4 :(得分:0)
我会这样做:
my_string = "yellow dogs are cooler than brown cats"
substitutions = {"yellow" => "black", "brown" => "grey"}
keys = substitutions.keys
arry_of_comb = 0.upto(substitutions.size).flat_map do |num|
keys.combination(num).map do |ary|
my_string.gsub(/\b#{Regexp.union(ary)}\b/,substitutions)
end
end
arry_of_comb
# => ["yellow dogs are cooler than brown cats",
# "black dogs are cooler than brown cats",
# "yellow dogs are cooler than grey cats",
# "black dogs are cooler than grey cats"]