2014-11-25 71 views
0

我有一個Haskell列表的列表。從每個列表中取一個元素時,我想獲得所有可能性。我目前擁有的是從列表清單中清除列表理解?

a = [ [1,2], [10,20,30], [-1,-2] ] -- as an example 
whatIWant = [ [p,q,r] | p <- a!!0, q <- a!!1, r <- a!!2 ] 

這就是我想要的。然而,這顯然不是很好的代碼,而且我正在尋找更好的方式來編寫列表理解,以便在代碼中不顯示索引號(0,1,2)...這就是我所在的位置卡住。

我該怎麼做?

+2

你堅持使用列表理解來做它嗎?我認爲對於這樣的任務來說,功能更好,更清潔。 – zegkljan 2014-11-25 10:15:53

+0

@JanŽegklitz感謝您的評論。這並不是說我堅持這樣做:我只是覺得用一個列表理解來寫一個好的,乾淨的方法,而且根本不知道這是否可行。 – Yosh 2014-11-25 10:19:13

+5

你想要所有列表的笛卡爾積。使用'序列a'來實現這一點。 http://stackoverflow.com/questions/3387359/calculate-n-ary-cartesian-product – chi 2014-11-25 10:27:44

回答

1

這顯然不是一個好的代碼

這是你能做到這一點的最好辦法,因爲你的約束輸入是列表的列表。

如果您使用其他類型,例如列表的三倍,那麼你可以在結構上進行索引。例如。

Prelude> let [email protected](a,b,c) = ([1,2], [10,20,30], [-1,-2]) 

讓你寫:

Prelude> [ (p,q,r) | p <- a , q <- b , r <- c ] 
[(1,10,-1),(1,10,-2),(1,20,-1) 
,(1,20,-2),(1,30,-1),(1,30,-2) 
,(2,10,-1),(2,10,-2),(2,20,-1) 
,(2,20,-2),(2,30,-1),(2,30,-2)] 

課:避免索引,使用類型,其結構捕捉你想要保持不變。將數據的維數提升到其類型。

+0

如果我必須處理大列表,那麼該怎麼辦?(x @(a,b,c,....,z,za) 。))'?我是否應該像@JanŽegklitz所建議的那樣尋求功能? //我只在模式匹配的情況下知道'@',這很好理解。 – Yosh 2014-11-25 10:20:56

2

使用功能(使用內部列表理解),我的解決辦法是

combinations :: [[a]] -> [[a]] 
combinations [] = [] 
combinations [l] = map (\ x -> [x]) l 
combinations (x:xs) = combine (combinations [x]) (combinations xs) 
    where combine a b = [ p ++ q | p <- a, q <- b ] 

例子:

*Main> combinations [[1, 2, 3], [4, 5, 6]] 
[[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]] 
*Main> combinations [['a', 'b', 'c'], ['A', 'B', 'C'], ['1', '2']] 
["aA1","aA2","aB1","aB2","aC1","aC2","bA1","bA2","bB1",... 
"bB2","bC1","bC2","cA1","cA2","cB1","cB2","cC1","cC2"] 

編輯:當然你可以使用sequence功能,在評論中提出:

*Main> sequence [['a', 'b', 'c'], ['A', 'B', 'C'], ['1', '2']] 
["aA1","aA2","aB1","aB2","aC1","aC2","bA1","bA2","bB1",... 
"bB2","bC1","bC2","cA1","cA2","cB1","cB2","cC1","cC2"]