我有一個給定的列表,例如[2, 3, 5, 587]
,我想要一個完整的組合列表。所以想要像[2, 2*3,2*5, 2*587, 3, 3*5, 3*587, 5, 5*587, 587]
。由於我在Haskell的初學者水平上,我很好奇列表操作是怎麼樣的。Haskell:整數的列表組合
此外,我很好奇,如果計算的基礎列表可能會很昂貴,這將如何影響功能的成本? (如果我將承擔名單有極限值,即< 20)
雷姆:列表的順序可以事後做,但我也實在沒有線索,如果是這樣的功能或之後內便宜。
我有一個給定的列表,例如[2, 3, 5, 587]
,我想要一個完整的組合列表。所以想要像[2, 2*3,2*5, 2*587, 3, 3*5, 3*587, 5, 5*587, 587]
。由於我在Haskell的初學者水平上,我很好奇列表操作是怎麼樣的。Haskell:整數的列表組合
此外,我很好奇,如果計算的基礎列表可能會很昂貴,這將如何影響功能的成本? (如果我將承擔名單有極限值,即< 20)
雷姆:列表的順序可以事後做,但我也實在沒有線索,如果是這樣的功能或之後內便宜。
因此,看來你想要的是列表中的所有對產品:
ghci> :m +Data.List
ghci> [ a * b | a:bs <- tails [2, 3, 5, 587], b <- bs ]
[6,10,1174,15,1761,2935]
但你也想inital號:
ghci> [ a * b | a:bs <- tails [2, 3, 5, 587], b <- 1:bs ]
[2,6,10,1174,3,15,1761,5,2935,587]
這將使用列表理解,但是這可能也可以通過定期列表操作完成:
ghci> concatMap (\a:bs -> a : map (a*) bs) . init $ tails [2, 3, 5, 587]
[2,6,10,1174,3,15,1761,5,2935,587]
後者有點容易解釋:
Data.List.tails
產生一個列表的所有後綴:
ghci> tails [2, 3, 5, 587]
[[2,3,5,587],[3,5,587],[5,587],[587],[]]
Prelude.init
從列表中滴的最後一個元素。在這裏,我使用它來刪除空白後綴,因爲在下一步中會導致錯誤的處理。
ghci> init [[2,3,5,587],[3,5,587],[5,587],[587],[]]
[[2,3,5,587],[3,5,587],[5,587],[587]]
ghci> init $ tails [2, 3, 5, 587]
[[2,3,5,587],[3,5,587],[5,587],[587]]
Prelude.concatMap
運行在一個列表的每個元素的功能,並且將結果組合成扁平列表。所以
ghci> concatMap (\a -> replicate a a) [1,2,3]
[1, 2, 2, 3, 3, 3]
\(a:bs) -> a : map (a*) bs
做了幾件事情。我的論點
init
放棄了空列表),配件初始元素爲a
和後來的元素融入bs
。a:
列表,但a
(map (a*) bs
)每個後來元件。OP後來在評論中澄清說他們想要所有的組合,而不僅僅是配對。這可能是爲了從素數分解中產生一個數的所有因數。 :) –
正確的意圖 - 良好的猜測,但給定的方法是錯誤的;)例如2 * 2 * 587不會導致除數4(!)但是給定的解決方案對於列表操作是很好的 - 這是我的目標之一,看看它是如何工作的。 – LeO
你可以使用Data.List.tails
列表的後綴。 這給你一個列表的列表,那麼你可以做你想做的內乘這個名單上有類似的功能:
prodAll [] = []
prodAll (h:t) = h:(map (* h) $ t)
然後,您可以映射在每個內部列表此功能並連接結果:
f :: Num a => [a] -> [a]
f = concat . map prodAll . tails
其他人解釋瞭如何做對,所以我在這裏關心自己與獲得的組合。
如果你想的所有長度的組合,這只是你的名單power set,並且可以計算方式如下:
powerset :: [a] -> [[a]]
powerset (x:xs) = let xs' = powerset xs in xs' ++ map (x:) xs'
powerset [] = [[]]
-- powerset [1, 2] === [[],[2],[1],[1,2]]
-- you can take the products:
-- map product $ powerset [1, 2] == [1, 2, 1, 2]
有哈斯克爾替代powerset
實現人們心目中的排序的經典:
import Control.Monad
powerset = filterM (const [True, False])
你可以看看filterM
的source,看看它是如何工作本質上是相同的方式爲行吟詩人以上爲powerset
。
在另一方面,如果你想有一定規模的所有組合,你可以做到以下幾點:
combsOf :: Int -> [a] -> [[a]]
combsOf n _ | n < 1 = [[]]
combsOf n (x:xs) = combsOf n xs ++ map (x:) (combsOf (n - 1) xs)
combsOf _ _ = []
-- combsOf 2 [1, 2, 3] === [[2,3],[1,3],[1,2]]
+1。最後一個也讓人想起SICP的「改變」。 :) ---一個相關的問題,雖然沒有被問到:如果在(有序)輸入中允許重複,產生所有獨特的組合。 –
@WillNess:我也很想回想起硬幣更換問題; [這裏](https://gist.github.com/AndrasKovacs/8686121),我前一段制定出來的,如果你有興趣一漂亮和快速的解決方案:) –
排列組合就意味着所有的列表中的元素,但在不同的順序打亂。你確定你不是指「組合」嗎?另外,你爲什麼只獲得1或2個元素的組,而不是3或4的組? – hugomg
是的,你是對的,沒有排列,更多的組合。你也是對的,雖然沒有明確提及,但三種組合的組是有意義的。但我想,根據建議,這應該是最後調整它的一小步。無論如何,你的問題/疑惑給了我一點思考'我想達成什麼?'。謝謝。 – LeO
[本SO問題](http://stackoverflow.com/questions/21265454/subsequences-of-length-n-from-list-performance/21268310)包含關於在Haskell生成組合了很好的討論。 – ErikR