ruby中字符串中所选字符替换的所有可能组合
我想知道是否有一种简单的方法以简单的方式在ruby中完成所选字符替换的每个组合。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"
感谢您的帮助!
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
如果我没有错,OP做错了结构..'['a'=>'@','i'=>'!','s'=>'$']'..应该是'Hash' .. 对 ? –
@ArupRakshit这不是一个散列,它是一个包含一个散列的数组,省略了{}。 – sawa
好的。它是一个哈希数组或只有哈希数组。 –
我下面做:
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这与我在打字前一直打字的内容类似(现在在通勤巴士上)。我注意到你有一个未使用的变量'new' –
@MarkThomas谢谢,我首先想到的是,我会创建'#map',因此'new'在那里。之后,我改变了我的决定,但忘了删除'new'变量。现在我做到了。 –
有趣的是对'sub!'使用散列参数,但我认为您不需要将匹配模式转换为正则表达式,对吗? – sawa
我会做使用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"]
好的解决方案,Abdo,+1。我不知道'gsub'可以把一个散列作为一个参数。很高兴知道。 –
@CarySwoveland是!我们的解决方案可以组合成以下内容:'keys.repeated_combination(keys.length).map {| c | string.gsub(/ [#{c.uniq.join}] /,subs)} .uniq' – Abdo
我喜欢那样。你会为我的皇室提出什么建议? –
甲单行官能溶液
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"]
矿是一个班轮...我只缩进它,你不必滚动。 – Abdo
我同意最好多行以获得可读性 –
根据官方规定,如果仅为了避免水平滚动的需要而显示在多行上,则其符合作为单行程的条件。我这样做的好方法是从.map开始第二行,位于.flat_map下面。 Ruby将没有问题(尽管IRB/Pry会)。 –
的另一种方法:
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
传递的string
每个字符c
到块
{|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"]
哦,是的!大量使用repeat_combination! +1 – Abdo
只是好奇,为什么你要生成的组合? –
它适用于我正在使用的计算机安全课程中的任务。我们要写一个密码破解器,给出一个单词列表应该破解我们的教授给我们的散列密码。以上是已经实现的,尽管以非常难看的方式将每个组合在脚本中进行硬编码。 – user3207230
你是否需要确切的预期产出,那么我需要更多地回答我的问题? –