我想知道是否有一种简单的方法可以用简单的方式在ruby中完成所选字符替换的每个组合。
一个例子:
string = "this is a test"
subs = ['a'=>'@','i'=>'!','s'=>'$']
subs.combination.each { |c|
string.gsub c
}
会产生
"this is @ test"
"th!s !s a test"
"thi$ i$ a te$t"
"th!s !s @ test"
"thi$ i$ @ te$t"
"th!$ !$ a te$t"
"th!$ !$ @ te$t"
感谢您的帮助!
答案 0 :(得分:3)
我会这样做:
string = "this is a test"
subs = {'a'=>'@','i'=>'!','s'=>'$'}
keys = subs.keys
combinations = 1.upto(subs.size).flat_map { |i| keys.combination(i).to_a }
combinations.each do |ary|
new_string = string.dup
ary.each { |c| new_string.gsub!(c,subs) }
puts new_string
end
<强>输出强>
this is @ test
th!s !s a test
thi$ i$ a te$t
th!s !s @ test
thi$ i$ @ te$t
th!$ !$ a te$t
th!$ !$ @ te$t
答案 1 :(得分:1)
string = "this is a test"
subs = ['a'=>'@','i'=>'!','s'=>'$']
subs = subs.first.map(&:to_a)
1.upto(subs.length).each do |n|
subs.combination(n).each do |a|
p a.each_with_object(string.dup){|pair, s| s.gsub!(*pair)}
end
end
答案 2 :(得分:1)
我使用String#gsub(pattern, hash)
执行以下操作:
string = "this is a test"
subs = {'a'=>'@','i'=>'!','s'=>'$'} # copied from @ArupRakshit
keys = subs.keys
核心代码:
1.upto(keys.length).flat_map { |i|
keys.combination(i).flat_map { |c| string.gsub(/[#{c.join}]/, subs) }
}
输出:
=> ["this is @ test",
"th!s !s a test",
"thi$ i$ a te$t",
"th!s !s @ test",
"thi$ i$ @ te$t",
"th!$ !$ a te$t",
"th!$ !$ @ te$t"]
答案 3 :(得分:1)
另一种方式:
string = "this is a test"
subs = [{"a"=>"@"}, {"i"=>"!"}, {"s"=>"$"}]
subs.repeated_combination(subs.size)
.map {|e| string.gsub(/./) {|c| (g = e.find {|h| h.key?(c)}) ? g[c] : c}}
.uniq
#=> ["this is @ test", "th!s !s @ test", "thi$ i$ @ te$t", "th!$ !$ @ te$t",
# "th!s !s a test", "th!$ !$ a te$t", thi$ i$ a te$t"]
说明:
a = subs.repeated_combination(subs.size)
# Enumerator...
a.to_a
# [[{"a"=>"@"},{"a"=>"@"},{"a"=>"@"}], [{"a"=>"@"},{"a"=>"@"},{"i"=>"!"}],
# [{"a"=>"@"},{"a"=>"@"},{"s"=>"$"}], [{"a"=>"@"},{"i"=>"!"},{"i"=>"!"}],
# [{"a"=>"@"},{"i"=>"!"},{"s"=>"$"}], [{"a"=>"@"},{"s"=>"$"},{"s"=>"$"}],
# [{"i"=>"!"},{"i"=>"!"},{"i"=>"!"}], [{"i"=>"!"},{"i"=>"!"},{"s"=>"$"}],
# [{"i"=>"!"},{"s"=>"$"},{"s"=>"$"}], [{"s"=>"$"},{"s"=>"$"},{"s"=>"$"}]]
b = a.map {|e| string.gsub(/./) {|c| (g = e.find {|h| h.key?(c)}) ? g[c] : c}}
#=> ["this is @ test", "th!s !s @ test", "thi$ i$ @ te$t", "th!s !s @ test",
# "th!$ !$ @ te$t", "thi$ i$ @ te$t", "th!s !s a test", "th!$ !$ a te$t",
# "th!$ !$ a te$t", "thi$ i$ a te$t"]
要了解如何计算b
,请考虑传递给块的a
的第二个元素:
e = [{"a"=>"@"},{"a"=>"@"},{"i"=>"!"}]
由于正则表达式,/./
,gsub
将c
的每个字符string
传递到块
{|c| (g = e.find {|h| h.key?(c)}) ? g[c] : c}
搜索e
以确定三个哈希值中的任何一个是否有c
作为键。如果找到一个,即g
,则将字符c
替换为g[c]
;否则,角色保持不变。
请注意e
的前两个元素是相同的。通过将第一行更改为:
subs.repeated_combination(subs.size).map(&:uniq)
但效率不是这种方法的优点之一。
回到主要计算,最后一步是:
b.uniq
#=> ["this is @ test", "th!s !s @ test", "thi$ i$ @ te$t", "th!$ !$ @ te$t",
# "th!s !s a test", "th!$ !$ a te$t", "thi$ i$ a te$t"]
答案 4 :(得分:0)
单行功能解决方案
string = "this is a test"
subs = {'a'=>'@','i'=>'!','s'=>'$'}
(1..subs.size).flat_map { |n| subs.keys.combination(n).to_a }.map { |c| string.gsub(/[#{c.join}]/, subs) }
# => ["this is @ test", "th!s !s a test", "thi$ i$ a te$t", "th!s !s @ test", "thi$ i$ @ te$t", "th!$ !$ a te$t", "th!$ !$ @ te$t"]