多个选项的Ruby字符串替换
我想做字符串替换。随着gsub
或tr
我可以给单个输入字符并将其映射到一个单一的输出值,但我想基于多个映射创建多个输出字符串:多个选项的Ruby字符串替换
swap = {
'a' => ['$', '%', '^'],
'b' => ['3'],
'c' => ['4', '@'],
}
对于输入字符串'abc'
,我应该得到下面的输出字符串:
'$34'
'[email protected]'
'%34'
'%[email protected]'
'^34'
'^[email protected]'
是否有一个简单的方法来对输入和映射任意数量的做到这一点?实际上,它可能是大约10个输入和最多3个映射,通常只有一个。
def gen_products(swap, str)
swap_all = Hash.new { |_,k| [k] }.merge(swap)
arr = swap_all.values_at(*str.chars)
arr.shift.product(*arr).map(&:join)
end
参见Hash::new(与块),Hash#values_at和Array#product。如果h = Hash.new { |_,k| [k] }
和h
没有密钥k
,则h[k]
返回[k]
。
swap = { 'a'=>['$', '%', '^'], 'b'=>['3'], 'c'=>['4', '@'] }
gen_products(swap, "abc")
#=> ["$34", "[email protected]", "%34", "%[email protected]", "^34", "^[email protected]"]
这里
swap_all = Hash.new { |_,k| [k] }.merge(swap)
#=> {"a"=>["$", "%", "^"], "b"=>["3"], "c"=>["4", "@"]}
vals = swap_all.values_at(*str.chars)
#=> [["$", "%", "^"], ["3"], ["4", "@"]]
又如:
gen_products(swap, "bca")
#=> ["34$", "34%", "34^", "[email protected]$", "[email protected]%", "[email protected]^"]
和一种或多种:
gen_products(swap, "axbycx")
#=> ["$x3y4x", "[email protected]", "%x3y4x", "%[email protected]", "^x3y4x", "^[email protected]"]
这里
swap_all = Hash.new { |_,k| [k] }.merge(swap)
#=> {"a"=>["$", "%", "^"], "b"=>["3"], "c"=>["4", "@"]}
vals = swap_all.values_at(*str.chars)
#=> [["$", "%", "^"], ["x"], ["3"], ["y"], ["4", "@"], ["x"]]
哦,这很聪明:)忘了'.product'。递归地重新实现它。这看起来不像性感。 –
您可以在分配过程中通过'first,* others = swap.values_at(* str.chars)'分解数组,以便将方法的第二行缩短为first.product(* others)' – Stefan
好主意, @Stefan。我知道有些事情不完全正确。我会改变它。谢谢。 –
这很简单(在这种情况下)有三个嵌套循环(枚举所有组合),并且在最内层的循环中调用tr/gsub。 –
虽然做一个通用的实现至少是非平凡的,我承认。不过试试吧。 –
罗宾,感谢您选择我的答案,但您在授予绿党之前确实应该等待一段时间(或许还有2个半小时)。快速选择可能会阻止其他答案,而对于仍然在寻求答案的其他人,imo是无礼的。没有急于。请考虑删除复选标记并稍后决定。 –