[英]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.