2011-03-08 25 views
27

我有數組的數組,像這樣:合併數組的數組轉換成所有可能的組合,只向前,在紅寶石

[['1','2'],['a','b'],['x','y']] 

我需要將這些陣列組合成含有所有三種的所有可能的組合的字符串設置,只轉發。我已經看到很多以任何順序組合的所有可能組合的例子,這不是我想要的。例如,我不希望第一組中的任何元素在第二組之後出現,或者第三組中的任何元素在第一組之前或第二組之前出現,以此類推。因此,對於上述示例,輸出將爲:

['1ax', '1ay', '1bx', '1by', '2ax', '2ay', '2bx', '2by'] 

數組的數量和每組的長度都是動態的。

有人知道如何在Ruby中解決這個問題嗎?

+0

可能重複(http://stackoverflow.com/questions/5543896/multiple -iterations) – 2011-04-05 04:49:25

+0

另請參見[從多維數組創建排列](http://stackoverflow.com/questions/5582481/creating-permutations-from-a-multi-dimensional-array-in-ruby) – aidan 2016-03-31 06:41:36

回答

52

KnowArray#product

a = [['1','2'],['a','b'],['x','y']] 
a.first.product(*a[1..-1]).map(&:join) 
+5

Sexytime!做得好。 – Phrogz 2011-03-08 00:36:28

+0

@ Travis:如果這回答你的問題,你可以勾選問題旁邊的勾號/複選標記。 – 2011-03-08 22:44:51

+0

它對我不起作用:它只給我提供'''''''''':/ – bfontaine 2012-02-24 22:39:29

6

使用遞歸解決,所謂"Dynamic Programming"的方法:

  • 對於n陣列,其中每個結果合併第一陣列的條目上的剩餘(N-1)陣列
  • 對於單個陣列,答案是隻是陣列

在代碼:

def variations(a) 
    first = a.first 
    if a.length==1 then 
    first 
    else 
    rest = variations(a[1..-1]) 
    first.map{ |x| rest.map{ |y| "#{x}#{y}" } }.flatten 
    end 
end 

p variations([['1','2'],['a','b'],['x','y']]) 
#=> ["1ax", "1ay", "1bx", "1by", "2ax", "2ay", "2bx", "2by"] 

puts variations([%w[a b],%w[M N],['-'],%w[x y z],%w[0 1 2]]).join(' ') 
#=> aM-x0 aM-x1 aM-x2 aM-y0 aM-y1 aM-y2 aM-z0 aM-z1 aM-z2 aN-x0 aN-x1 aN-x2 
#=> aN-y0 aN-y1 aN-y2 aN-z0 aN-z1 aN-z2 bM-x0 bM-x1 bM-x2 bM-y0 bM-y1 bM-y2 
#=> bM-z0 bM-z1 bM-z2 bN-x0 bN-x1 bN-x2 bN-y0 bN-y1 bN-y2 bN-z0 bN-z1 bN-z2 

你也可以反轉邏輯,並小心你應該能夠實現這個非遞歸。但遞歸答案相當簡單。 :)

+1

很好地編碼,地圖和遞歸! – macarthy 2011-03-08 00:28:57

3

純,減少產品:

a = [['1','2'],['a','b'],['x','y']] 
a.reduce() { |acc, n| acc.product(n).map(&:flatten) }.map(&:join) 
# => ["1ax", "1ay", "1bx", "1by", "2ax", "2ay", "2bx", "2by"] 
的[多次迭代]