簡體   English   中英

如何從Haskell中的兩個列表中提取相同的元素?

[英]How to extract the same elements from two lists in Haskell?

這是我的問題:如何從兩個相等長度的列表中提取相同的元素到另一個列表? 例如:給出兩個列表[2,4,6,3,2,1,3,5][7,3,3,2,8,8,9,1] ,答案應該是[1,2,3,3] 請注意,訂單並不重要。 我實際上正在使用返回列表的長度。

我試過這個:

sameElem as bs = length (nub (intersect as bs))

但問題是nub刪除所有重復。 在前一個例子中使用my函數的結果是[1,3,2]的長度為3而不是[1,3,3,2]的長度為4 有解決方案嗎? 謝謝。

你可以為此編寫一個函數。 可能有更優雅的版本涉及lambda或折疊,但這適用於您的示例:

import Data.List

same (x:xs) ys = if x `elem` ys
                 then x:same xs (delete x ys)
                 else same xs ys
same [] _ = []
same _ [] = []

then子句中的delete x ys很重要,如果沒有那個刪除命令,那么第一個列表中至少出現一次的命令項將在每次遇到時計算。
請注意,輸出未排序,因為您只對結果列表的長度感興趣。

由於該位置似乎無關緊要,您可以事先對列表進行排序,然后遍歷兩個列表:

import Data.List (sort)

intersectSorted :: Ord a => [a] -> [a] -> [a]
intersectSorted (x:xs) (y:ys) 
 | x == y    = x : intersectSorted xs ys
 | x < y     = intersectSorted xs (y:ys)
 | x > y     = intersectSorted (x:xs) ys
intersectSorted _ _ = []

intersect :: Ord a => [a] -> [a] -> [a]
intersect xs ys = intersectSorted (sort xs) (sort ys)

請注意,也可以使用Map實現此目的:

import Data.Map.Strict (fromListWith, assocs, intersectionWith, Map)

type Counter a = Map a Int 

toCounter :: Ord a => [a] -> Counter a
toCounter = fromListWith (+) . flip zip (repeat 1)

intersectCounter :: Ord a => Counter a -> Counter a -> Counter a
intersectCounter = intersectionWith min

toList :: Counter a -> [a]
toList = concatMap (\(k,c) -> replicate c k) . assocs

intersect :: Ord a => [a] -> [a] -> [a]
intersect xs ys = toList $ intersectCounter (toCounter xs) (toCounter ys)
import Data.List (delete)

mutuals :: Eq a => [a] -> [a] -> [a]
mutuals []       _                = []
mutuals (x : xs) ys | x `elem` ys = x : mutuals xs (delete x ys)
                    | otherwise   = mutuals xs ys

mutuals [2,4,6,3,2,1,3,5] [7,3,3,2,8,8,9,1]  ==  [2,3,1,3]

暫無
暫無

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

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