簡體   English   中英

Haskell將列表的唯一組合添加到元組

[英]Haskell add unique combinations of list to tuple

例如說我有一個這樣的清單

list = ["AC", "BA"]

我想將此列表的每個唯一組合添加到元組,因此結果如下所示:

[("AC", "AC"),("AC","BA"),("BA", "BA")]

其中("BA","AC")被排除。

我的第一種方法是使用像這樣的列表理解:

ya = [(x,y) | x <- list, y <- list]

但是我無法使其正常工作,是否有任何通過使用列表推導來達到目的的結果?

我的首選解決方案使用列表理解

f :: [t] -> [(t, t)]
f list = [ (a,b) | theTail@(a:_) <- tails list , b <- theTail ]

我發現這很容易理解:首先選擇a(不確定地)后綴theTail ,從a開頭,然后選擇(不確定地)選擇后綴的元素b 最終,生成了對(a,b) ,該對顯然在所需對的范圍內。

它還應該是最佳效率的:每次您需要元素時,它都是在恆定時間內生成的。

ThreeFx的答案會起作用,但是它增加了元素必須可排序的約束。 取而代之的是,您可以擺脫PreludeData.List函數,從而更有效,更通用地實現此功能:

import Data.List (tails)

permutations2 :: [a] -> [(a, a)]
permutations2 list
    = concat
    $ zipWith (zip . repeat) list
    $ tails list

它不使用列表推導,但無需執行可能比較昂貴的比較,並且對可以通過哪種值進行任何約束都可以使用。


要查看其工作原理,請考慮如果您具有列表[1, 2, 3] ,則將具有組

[(1, 1), (1, 2), (1, 3),
         (2, 2), (2, 3),
                 (3, 3)]

這相當於

[(1, [1, 2, 3]),
 (2,    [2, 3]),
 (3,       [3])]

因為它不包含任何額外或更少的信息。 從這個表格到期望的輸出變換為映射函數f (x, ys) = map (\\y -> (x, y)) ys在每個元組,那么concat一起它們。 現在,我們只需要弄清楚如何獲取這些元組的第二個元素。 很明顯,我們看到它所做的所有事情都是將連續的元素從列表的前面刪除。 幸運的是,這已經通過Data.Listtails函數為我們實現了。 每個元組中的第一個元素就是原始列表,因此我們知道可以使用zip 最初,您可以使用

> concatMap (\(x, ys) -> map (\y -> (x, y)) ys) $ zip list $ tails list

但是我個人更喜歡zip ,所以我將內部函數變成了一個不需要使用lambda的函數:

> concatMap (\(x, ys) -> zip (repeat x) ys) $ zip list $ tails list

而且由於我更喜歡zipWith f不是map (uncurry f) . zip map (uncurry f) . zip ,我會把它變成

> concat $ zipWith (\x ys -> zip (repeat x) ys) list $ tails list

現在,我們可以進一步減少:

> concat $ zipWith (\x -> zip (repeat x)) list $ tails list
> concat $ zipWith (zip . repeat) list $ tails list

感謝eta減少和功能組成。 我們可以使這個完全沒有意義

> permutations2 = concat . ap (zipWith (zip . repeat)) tails

但是我發現這很難閱讀和理解,所以我認為我會堅持使用以前的版本。

只需使用列表理解即可:

f :: (Ord a) => [a] -> [(a, a)]
f list = [ (a, b) | a <- list, b <- list, a <= b ]

由於Haskell的StringOrd類型類中,這意味着可以排序,因此您首先告訴Haskell獲取所有可能的組合,然后排除b大於a所有組合,從而刪除所有“重復”組合。

輸出示例:

> f [1,2,3,4]
[(1,1),(1,2),(1,3),(1,4),(2,2),(2,3),(2,4),(3,3),(3,4),(4,4)]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM