2014-02-27 82 views
3

我想知道是否有一种简单的方法以简单的方式在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" 

感谢您的帮助!

+1

只是好奇,为什么你要生成的组合? –

+0

它适用于我正在使用的计算机安全课程中的任务。我们要写一个密码破解器,给出一个单词列表应该破解我们的教授给我们的散列密码。以上是已经实现的,尽管以非常难看的方式将每个组合在脚本中进行硬编码。 – user3207230

+0

你是否需要确切的预期产出,那么我需要更多地回答我的问题? –

回答

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

如果我没有错,OP做错了结构..'['a'=>'@','i'=>'!','s'=>'$']'..应该是'Hash' .. 对 ? –

+0

@ArupRakshit这不是一个散列,它是一个包含一个散列的数组,省略了{}。 – sawa

+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这与我在打字前一直打字的内容类似(现在在通勤巴士上)。我注意到你有一个未使用的变量'new' –

+0

@MarkThomas谢谢,我首先想到的是,我会创建'#map',因此'new'在那里。之后,我改变了我的决定,但忘了删除'new'变量。现在我做到了。 –

+1

有趣的是对'sub!'使用散列参数,但我认为您不需要将匹配模式转换为正则表达式,对吗? – sawa

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

好的解决方案,Abdo,+1。我不知道'gsub'可以把一个散列作为一个参数。很高兴知道。 –

+0

@CarySwoveland是!我们的解决方案可以组合成以下内容:'keys.repeated_combination(keys.length).map {| c | string.gsub(/ [#{c.uniq.join}] /,subs)} .uniq' – Abdo

+0

我喜欢那样。你会为我的皇室提出什么建议? –

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

矿是一个班轮...我只缩进它,你不必滚动。 – Abdo

+1

我同意最好多行以获得可读性 –

+0

根据官方规定,如果仅为了避免水平滚动的需要而显示在多行上,则其符合作为单行程的条件。我这样做的好方法是从.map开始第二行,位于.flat_map下面。 Ruby将没有问题(尽管IRB/Pry会)。 –

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

哦,是的!大量使用repeat_combination! +1 – Abdo

相关问题