我有两个列表
a = [1,2,3,4,5,6]
b = [3,4,5,6,7,8,9]
我想得到的结果是这两个列表的共同部分:[3,4,5,6]
我试图使用过滤功能,但它总是输出错误
filter (== a) b
filter (== b) a
然后将它们组合在一起
答案 0 :(得分:6)
您需要使用filter
迭代一个列表,并使用elem
函数检查该列表中的元素是否出现在另一个列表中:
inte :: Eq a => [a] -> [a] -> [a]
inte a b = filter (\x -> x `elem` a) b
另一种方法是查看是否存在任何内置库函数。首先,为所需函数编写类型签名:
[a] -> [a] -> [a]
然后运行hoogle query以查看是否有任何预建功能。 intersect
中有一个Data.List
功能,可以完全实现您的目标。
答案 1 :(得分:4)
如果只查看常用元素,请使用intersect
Data.List
a `intersect` b == [3,4,5,6]
相关问题:is there union and intersect Haskell Prelude implementation?
答案 2 :(得分:2)
您需要使用 intersect 函数从两个列表中获取常用元素。
了解如何在列表中使用intersect功能。
答案 3 :(得分:1)
虽然您可以直接在列表中使用intersect
函数,但我建议您使用更高效的专用容器而不是列表。如果您真的想表达集,那么为什么不使用Data.Set
?
前奏>导入合格的数据。设置为设置
前奏集>设a = Set.fromList [1,2,3,4,5,6]; b = Set.fromList [3,4,5,6,7,8,9]
加载包数组-0.5.0.0 ...链接...完成。
加载包deepseq-1.3.0.2 ...链接...完成。
装箱包装容器-0.5.5.1 ...连接......完成。
前奏集> Set.intersection a b
fromList [3,4,5,6]
这是 O ( n ⋅log n )而不是 O ( n 2 ),对于大型集合来说要快得多。此外,如果您使用专用的集合类型,它会更好地表达您的意图:它清楚地表明您计算重复项,并且没有任何重要的元素排序。
缺点是,元素需要Ord
,因为实现使用规范排序。另一种选择是HashSet
。
答案 4 :(得分:1)
这是一个单行
[x | x <- a, y <- b, x == y ]
答案 5 :(得分:1)
intersect a b = [x| x <- a, x `elem` b]
在a
中使用列表x <- a
参数作为生成器。布尔表达式x elem b
过滤每个元素。如果True添加到x
则丢弃。
答案 6 :(得分:0)
如果您的列表是由增加的正数构建的,那么您可以使用O(n)解决方案而不是二次intersect
和朋友:
ordzip :: (Ord a, Num a) => [a] -> [a] -> [(a,a)]
ordzip a b = g a b where
g a@(x:r) b@(y:q) | x < y = (x,0) : g r b
| y < x = (0,y) : g a q
| otherwise = (x,y) : g r q
g a [] = [(x,0) | x <- a]
g [] b = [(0,y) | y <- b]
diff xs ys = [x | (x,y)<- ordzip xs ys, x/=0 && y==0 ] -- set difference
meet xs ys = [y | (x,y)<- ordzip xs ys, x/=0 && y/=0 ] -- intersection
joyn xs ys = [z | (x,y)<- ordzip xs ys, let z=max x y] -- union
您想要的是meet
:
前奏&GT;符合[1,2,3,4,5,6] [3,4,5,6,7,8,9]
[3,4,5,6]
上面只是一个玩具代码,给我们一个想法。通常情况下,您可以使用Maybe a
来传达可能值的信息,而不是使用特殊分隔的元素,就像我上面使用0
一样。类型Maybe a
的值可以是Nothing
或Just a
。
但实际上,我们永远不会有(Nothing, Nothing)
组合,因为我们选择ordzip
中的两个或两个中的一个,但从不 none ,对吧?所以我们真正需要的是Data.These.These
:
import Data.These
ordzip :: (Ord a) => [a] -> [b] -> [These a b]
ordzip a@(x:t) b@(y:r) = case compare x y of
LT -> This x : ordzip t b
GT -> That y : ordzip a r
EQ -> These x y : ordzip t r
ordzip a [] = map This a
ordzip [] b = map That b
diff = catThis .: ordzip
meet = map snd .: catThese .: ordzip
joyn = map (these id id const) .: ordzip
-- infixr 8 .: ; (f .: g) x y = f (g x y)
通过将它们的定义与上面的ordzip
合并来重写这三个集函数可以在某些情况下导致更高效的代码(例如,不需要使用ordzip a []
或{{附加额外的尾部1}}只是因为它们在ordzip [] b
中被丢弃了。而且,当其中一个参数列表是无限的而另一个是有限的时,它会使meet
(或meet
)正常生产。上面的三个定义更多是可执行规范。
有时我们可能需要通过一些额外的谓词来决定相等性,而不仅仅是普通的diff
,我们可能会以不同的方式构造结果的元素,因为我们可能需要它们(例如包括{{1} }和compare
中的结果x
。
这些功能适用于有序列表。还有data-ordlist package,其中包含更多工具。