我正在寻找一种与Ruby中的Python itertools.product
具有相同效果的方法。请使用以下Python代码:
from itertools import product
chars = []
for i in range(97,123):
chars.append(chr(i))
for a in range(1,3):
for i in product(chars,repeat=a):
s = ''.join(i)
print s
输出如下内容:
a, b, c... x, y, z, aa, ab, ac... ax, ay, az, ba, bb, bc.. etc.
我试图把它翻译成Ruby:
(1..2).each do |n|
('a'..'z').to_a.combination(n).each do |c|
s = c.join
puts s
end
end
但输出并不相同。单字符的工作正常(a-z),但当它进入两个字符的时候,它没有像我预期的那样工作:
ab, ac, ad.. ax, ay, az, bc, bd, be
它不会生成aa
,ba
或bb
- 所以它似乎生成所有组合而不重复字符或其他内容?
那么我应该使用什么方法来生成所有像itertools.product
这样的组合?
答案 0 :(得分:3)
答案 1 :(得分:3)
我会写(简化为3个元素,需要Ruby 1.9):
xs = ["a", "b", "c"]
strings = 1.upto(xs.size).flat_map do |n|
xs.repeated_permutation(n).map(&:join)
end
#=> ["a", "b", "c", "aa", "ab", "ac", ..., "cca", "ccb", "ccc"]
一个懒惰的解决方案:您可以使用each
而不是map
来轻松编写它,但让我们从Ruby 2.0中检查“懒惰”:
xs = ("a".."z").to_a
strings = 1.upto(xs.size).lazy.flat_map do |n|
xs.repeated_permutation(n).lazy.map(&:join)
end
答案 2 :(得分:2)
魔术(虽然不是很漂亮):
a = ('a'..'z').to_a
result = (0..2).map { |n|
a.product(*n.times.inject([]) { |s,x| s << a }) }.map { |x| x.map(&:join) }
}
puts result
说明:为了作为python product
工作,你需要在n-1
参数中重复数组product
次。
所以product('abc', repeat=n)
在ruby中与:
a = ['a','b','c']
a.product() # n = 1
a.product(a) # n = 2
a.product(a, a) # n = 3
这就是讨厌的inject
在上面的代码中的作用。它自动构建这样一个“参数数组”。但它不是非常有效的代码,所以不要试图用它来构建大型“产品”。
答案 3 :(得分:1)
在我写完之后,我注意到Casper的解决方案基本相同。有些人可能会发现这个更具可读性,所以我要离开它..
arr = ['a', 'b', 'c']
p (0..2).inject([]) { |acc, a|
acc + arr.product(*[arr]*a).map(&:join)
}
=> ["a", "b", "c", "aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc", "aaa", "aab", "aac", "aba", "abb", "abc", "aca", "acb", "acc", "baa", "bab", "bac", "bba", "bbb", "bbc", "bca", "bcb", "bcc", "caa", "cab", "cac", "cba", "cbb", "cbc", "cca", "ccb", "ccc"]
键“陷阱”将是
*[arr]*a
,首先创建一个a
arr
的数组,然后将其展开为a
方法的product
个参数。map(&:join)
,这是map{|e| e.join}
inject
(又名“减少”,来自“map-reduce”的名声),FP支柱之一答案 4 :(得分:1)
在ruby中,Array#product产生Cathesian产品。添加原始数组会产生相同的结果。
ar = (?a..?z).to_a
ar + ar.product(ar).map(&:join)
答案 5 :(得分:0)
在托克兰的帮助下,我明白了:
(1..2).each do |n|
('a'..'z').to_a.repeated_permutation(n).each do |a|
s = a.join
puts s
end
end
它很懒,所以当你用它来生成更长的字符串时它不会占用内存。