a = [1,2,3,4,5]
b = [1,3,5,6]
c = a and b
print c

实际输出:[1,3,5,6] 预期输出:[1,3,5]

如何在两个列表上实现布尔AND操作(列表交集)?


当前回答

使用过滤器和lambda运算符可以实现函数式的方法。

list1 = [1,2,3,4,5,6]

list2 = [2,4,6,9,10]

>>> list(filter(lambda x:x in list1, list2))

[2, 4, 6]

编辑:它过滤掉了同时存在于list1和list中的x,集差异也可以使用:

>>> list(filter(lambda x:x not in list1, list2))
[9,10]

python3 filter返回一个过滤器对象,用list封装它返回输出列表。

其他回答

这样可以得到两个列表的交集,也可以得到公共重复项。

>>> from collections import Counter
>>> a = Counter([1,2,3,4,5])
>>> b = Counter([1,3,5,6])
>>> a &= b
>>> list(a.elements())
[1, 3, 5]

在这种情况下,你有一个列表的列表地图很方便:

>>> lists = [[1, 2, 3], [2, 3, 4], [2, 3, 5]]
>>> set(lists.pop()).intersection(*map(set, lists))
{2, 3}

适用于类似的迭代对象:

>>> lists = ['ash', 'nazg']
>>> set(lists.pop()).intersection(*map(set, lists))
{'a'}

如果列表是空的,Pop会爆炸,所以你可能想要在一个函数中进行包装:

def intersect_lists(lists):
    try:
        return set(lists.pop()).intersection(*map(set, lists))
    except IndexError: # pop from empty list
        return set()

从较大的集合中创建一个集合:

_auxset = set(a)

然后,

c = [x for x in b if x in _auxset]

会做你想做的(保留b的顺序,而不是a的顺序——不一定能同时保留两者),而且动作要快。(使用a中的if x作为列表理解中的条件也可以工作,并且避免了构建_auxset的需要,但不幸的是,对于相当长的列表,它会慢得多)。

如果你想对结果进行排序,而不是保持列表的顺序,一个更整洁的方法可能是:

c = sorted(set(a).intersection(b))

如果布尔与是指同时出现在两个列表中的项,例如交集,那么你应该看看Python的set和frozenset类型。

如果顺序不重要,你不需要担心重复,那么你可以使用set intersection:

>>> a = [1,2,3,4,5]
>>> b = [1,3,5,6]
>>> list(set(a) & set(b))
[1, 3, 5]