2014-03-01 12 views
3

我试图显示子串替换的所有可能选项。举例来说,如果我有这样的字符串:显示Ruby中的所有子串替换选项

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

嗯。您所需的输出似乎不完整;你不想另外考虑其他两种可能性:'[“黄狗比棕色的猫冷”,“黄狗比灰猫冷”] – grenierm5

+0

感谢您的支持。添加。 – user2270029

回答

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"] 
+0

很酷。如果有两个替代选项,我怎么才能使它工作?例如,替换= {“黄色”=>“黑色”,“棕色”=>“灰色”,“棕色”=>“蓝色”} – user2270029

+0

@ user2270029从我的类似[answer](http:// stackoverflow.com/a/22068328/2767755)。 –

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 

输出:黑色的狗是不是灰色的猫

+1

这是做了一个变化,但正如我上面所述,我需要所有可能的变化。请参阅所需的输出。谢谢。 – user2270029

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操作,因为你想必想要替换“棕色”而不是“布朗尼”。另一方面,这不能很好地处理标点符号,所以你可以选择sub或更复杂的正则表达式操作。由你决定。

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的块形式产生找到的文本,然后用它来查找所需的替换(有时与原始字符串相同)。

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"