我假设列表的大小相同。
两个列表的区别
让我们关注问题的主要部分:
Prelude> a=["A1","A2","B3","C3"]
Prelude> b=["A1","B2","B3","D5"]
首先,请注意zip 方法压缩了两个列表。如果你在a 和b 上使用它,你会得到:
Prelude> zip a b
[("A1","A1"),("A2","B2"),("B3","B3"),("C3","D5")]
好的。现在是一对一比较这些术语的时候了。有很多方法可以做到。
过滤器
Prelude> filter(\(x,y)->x/=y)(zip a b)
[("A2","B2"),("C3","D5")]
如果对的元素不同(/= 运算符),则 lambda 函数返回 True。因此,过滤器只保留不匹配的对。
没关系,但你必须做更多的工作才能只保留每对的第二个元素。
Prelude> map(snd)(filter(\(x,y)->x/=y)(zip a b))
["B2","D5"]
map(snd) 将snd 应用于每个不一致的对,它只保留一对的第二个元素。
折叠
折叠更通用,可用于实现过滤器。让我们看看如何:
Prelude> foldl(\l(x,y)->if x==y then l else l++[y])[](zip a b)
["B2","D5"]
lambda 函数获取每一对 (x,y) 并比较这两个元素。如果它们具有相同的值,则累加器列表保持相同,但如果值不同,则累加器列表将增加第二个元素。
列表理解
这更紧凑,对每个 Python 程序员来说都应该是显而易见的:
Prelude> [y|(x,y)<-zip a b, x/=y] -- in Python [y for (x,y) in zip(a,b) if x!= y]
["B2","D5"]
元素个数
你想要一对元素的数量和元素本身。
折叠
使用折叠,简单但麻烦:您将使用稍微复杂一点的累加器,它同时存储差异 (l) 和差异的数量 (n)。
Prelude> foldl(\(n,l)(x,y)->if x==y then (n,l) else (n+1,l++[y]))(0,[])$zip a b
(2,["B2","D5"])
拉姆达
但是你可以利用你的输出是多余的这一事实:你想要一个列表,前面有该列表的长度。为什么不应用能完成这项工作的 lambda?
Prelude> (\x->(length x,x))[1,2,3]
(3,[1,2,3])
通过列表理解,它给出:
Prelude> (\x->(length x,x))[y|(x,y)<-zip a b, x/=y]
(2,["B2","D5"])
绑定运算符
最后,为了好玩,您不需要以这种方式构建 lambda。你可以这样做:
Prelude> ((,)=<<length)[y|(x,y)<-zip a b,x/=y]
(2,["B2","D5"])
这里发生了什么? (,) 是一个由两个元素组成一对的运算符:
Prelude> (,) 1 2
(1,2)
和((,)=<<length) : 1. 获取一个列表(技术上是Foldable)并将其传递给length 函数; 2. 然后列表和长度由=<<(“绑定”运算符)传递给(,) 运算符,因此得到预期的结果。
部分结论
- “方法不止一种”(但不是 Perl!)
- Haskell 提供了许多内置函数和运算符来处理这种基本操作。