All possible combinations of selected character substitution in a string in ruby

前端 未结 5 938
悲&欢浪女
悲&欢浪女 2020-12-18 11:07

I was wondering if there is a simple way to do every combination of selected character substitutions in ruby in a simple way.

An example:

    string          


        
5条回答
  •  臣服心动
    2020-12-18 11:48

    Another way:

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

    Explanation:

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

    To see how b is computed, consider the second element of a that is passed to the block:

        e = [{"a"=>"@"},{"a"=>"@"},{"i"=>"!"}]
    

    Because of the regex, /./, gsub passes each character c of string to the block

        {|c| (g = e.find {|h| h.key?(c)}) ? g[c] : c}
    

    A search is made of e to determine if any of the three hashes has c as a key. If one is found, namely, g, the character c is replaced with g[c]; else, the character is left unchanged.

    Notice that the first two elements of e are the same. Efficiency could be improved by changing the first line to:

        subs.repeated_combination(subs.size).map(&:uniq)
    

    but efficiency is not one of the virtues of this approach.

    Returning to the main calculation, the final step is:

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

提交回复
热议问题