ruby中字符串中所选字符替换的所有可能组合
我想知道是否有一种简单的方法可以用简单的方式在ruby中完成所选字符替换的每个组合。
一个例子:
string = "this is a test" subs = ['a'=>'@','i'=>'!','s'=>'$'] subs.combination.each { |c| string.gsub c }
会屈服
"this is @ test" "th!s !sa test" "thi$ i$ a te$t" "th!s !s @ test" "thi$ i$ @ te$t" "th!$ !$ a te$t" "th!$ !$ @ te$t"
谢谢您的帮助!
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
我会这样做:
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 !sa test thi$ i$ a te$t th!s !s @ test thi$ i$ @ te$t th!$ !$ a te$t th!$ !$ @ te$t
我使用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 !sa test", "thi$ i$ a te$t", "th!s !s @ test", "thi$ i$ @ te$t", "th!$ !$ a te$t", "th!$ !$ @ te$t"]
其他方式:
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 !sa 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 !sa test", "th!$ !$ a te$t", # "th!$ !$ a te$t", "thi$ i$ a te$t"]
要查看如何计算b
,请考虑传递给块的第二个元素:
e = [{"a"=>"@"},{"a"=>"@"},{"i"=>"!"}]
由于正则表达式,/。/, gsub
将string
每个字符c
传递给块
{|c| (g = e.find {|h| h.key?(c)}) ? g[c] : c}
搜索e
以确定三个哈希中的任何一个是否具有c
作为关键字。 如果找到一个,即g
,则用g[c]
替换字符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 !sa test", "th!$ !$ a te$t", "thi$ i$ a te$t"]
一线function解决方案
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 !sa test", "thi$ i$ a te$t", "th!s !s @ test", "thi$ i$ @ te$t", "th!$ !$ a te$t", "th!$ !$ @ te$t"]