生成长度在给定范围内的数组的所有可能组合

时间:2013-01-21 02:08:52

标签: ruby arrays combinations

如何生成长度在给定范围内的数组元素的所有可能组合? E.g:

('a'..'f').to_a.all_possibilities(3, 5)

应该生成如下数组:

['abc', 'abd', 'abe', 'abf', ..., 'abcde', 'abcdf', 'abcda', ...]

包括从"abc"(三个字符)到('a'..'f').to_a的最后一个可能组合,长度为五个字符。我不知道该怎么做。有什么帮助吗?

4 个答案:

答案 0 :(得分:50)

Array#combination是stdlib:

[1] pry(main)> a = ('a'..'f').to_a
=> ["a", "b", "c", "d", "e", "f"]
[2] pry(main)> a.combination(3).to_a
=> [["a", "b", "c"],
 ["a", "b", "d"],
 ["a", "b", "e"],
 ["a", "b", "f"],
 ["a", "c", "d"],
 ["a", "c", "e"],
 ["a", "c", "f"],
 ["a", "d", "e"],
 ["a", "d", "f"],
 ["a", "e", "f"],
 ["b", "c", "d"],
 ["b", "c", "e"],
 ["b", "c", "f"],
 ["b", "d", "e"],
 ["b", "d", "f"],
 ["b", "e", "f"],
 ["c", "d", "e"],
 ["c", "d", "f"],
 ["c", "e", "f"],
 ["d", "e", "f"]]

如果你想要所有尺寸min到max的组合:

(min..max).flat_map{|size| a.combination(size).to_a }

如果您希望将它们转换为字符串,只需将.to_a替换为.map(&:join)

答案 1 :(得分:13)

(3..5).flat_map{|n| ('a'..'f').to_a.combination(n).map(&:join)}

编辑:为了达到OP的明确意图,请使用repeated_permutation

(3..5).flat_map{|n| ('a'..'f').to_a.repeated_permutation(n).map(&:join)}

答案 2 :(得分:2)

您可以通过这种方式修改我对上一个问题的回复,以获得您想要的内容。

class Array
  def all_possibilities(from, to)
    (from..to).flat_map do |i|
      if i < size
        permutation(i).to_a 
      else
        permutation(to - i).flat_map do |e|
          (self + e).permutation.to_a
        end
      end
    end.map(&:join)
  end
end

array = ["F", "E", "R", "N", "A", "D", "O"]
array.all_possibilities(3, 8)

答案 3 :(得分:2)

`

D = length of array
N = number of possible values. i.e a-z = 26
possible combinations = N ^ D
array = [possible values]

map26 = '0123456789abcdefghijklmnop'
map10 = 'abcdefghijklmnopqrstuvwxyz'

combo = '' 
for 0...N ** D do |i|
  i.to_s(D).split(//).each do |v|  
    combo += map10[map26.index(v)].chr
  end
  puts combo
  combo = ''
end

`

编辑:请原谅上面的简洁,在浏览另一个答案的同时在iPad上砍掉它。我错了。

假设您希望a-z的所有组合最多3列。

所有组合均为26 * 26 * 26 = 26 ** 3 = 17576

让数组的0个起点减去1 = 17575

我们还需要一个映射变量,map26是一列的基础26查找

map26 = '0123456789abcdefghijklmnop'
map10 = 'abcdefghijklmnopqrstuvwxyz'

返回我们的最大组合

17575.to_s(26)
=> "ppp"

从map26中提取'p'的索引并将其放在map10中:

map10[map26.index('p')]   (add .chr for ruby ~ 1.8)
=> "z"

因此,如果您对上面的“ppp”进行切片和切块,您将获得“zzz”的最大组合

您还可以从映射变量中看到“000”将映射到“aaa”

我修改了原始代码以包含这些更改。

关于原始问题,您可以使用D来控制字符串的最大长度,并使用for循环的起始值来控制最小长度。