如何比较python中的两个列表并返回匹配项
Posted
技术标签:
【中文标题】如何比较python中的两个列表并返回匹配项【英文标题】:How can I compare two lists in python and return matches 【发布时间】:2010-11-26 04:56:20 【问题描述】:我想获取两个列表并找到两个列表中出现的值。
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
returnMatches(a, b)
例如会返回[5]
。
【问题讨论】:
下面的答案对我来说似乎都是错误的。如果一个数字在任一列表中重复会发生什么,您肯定想知道 (?)(例如,说两个列表都有两次“5”)任何使用集合的解决方案都会立即删除所有重复的项目,你会输那个信息。 How to find list intersection?的可能重复 【参考方案1】:不是最有效的方法,但迄今为止最明显的方法是:
>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
5
如果顺序很重要,您可以使用这样的列表推导来做到这一点:
>>> [i for i, j in zip(a, b) if i == j]
[5]
(仅适用于大小相等的列表,这意味着顺序重要性)。
【讨论】:
请注意,列表理解不一定是更快的选择。对于较大的集合(性能最重要),按位比较 (&
) 或 set(a).intersection(b)
将与列表理解一样快或更快。
另一个注意事项:列表推导式查找出现在两个相同位置的值(这就是 SilentGhost 的“顺序很重要”的意思)。设置的交叉点解决方案还将在不同的位置找到匹配项。这些是对 2 个完全不同的问题的答案......(操作员的问题对于它所问的问题是模棱两可的)
如果您的列表是列表列表,即 a = [[0,0], [1,0]] 和 b = [[2,3],[0,0 ]]
第一个例子set(a) & set(b)
的时间复杂度是多少?
您如何找到例如在列表 A 中但不在列表 B 中的项目?【参考方案2】:
使用set.intersection(),它既快速又易读。
>>> set(a).intersection(b)
set([5])
【讨论】:
这个答案有很好的算法性能,因为只有一个列表(应该更短)被变成一个快速查找的集合,另一个列表被遍历查找它在集合中的项目。bool(set(a).intersection(b))
for True
或 False
这个答案更加灵活易读,因为人们可能需要difference
或union
。
如果我有对象作为列表元素并且只想要部分匹配,即只有一些属性必须匹配才能被视为匹配对象?
.intersection()
与 &
的性能有何不同?【参考方案3】:
显示 Lutz 解决方案的快速性能测试是最好的:
import time
def speed_test(func):
def wrapper(*args, **kwargs):
t1 = time.time()
for x in xrange(5000):
results = func(*args, **kwargs)
t2 = time.time()
print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0)
return results
return wrapper
@speed_test
def compare_bitwise(x, y):
set_x = frozenset(x)
set_y = frozenset(y)
return set_x & set_y
@speed_test
def compare_listcomp(x, y):
return [i for i, j in zip(x, y) if i == j]
@speed_test
def compare_intersect(x, y):
return frozenset(x).intersection(y)
# Comparing short lists
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
compare_bitwise(a, b)
compare_listcomp(a, b)
compare_intersect(a, b)
# Comparing longer lists
import random
a = random.sample(xrange(100000), 10000)
b = random.sample(xrange(100000), 10000)
compare_bitwise(a, b)
compare_listcomp(a, b)
compare_intersect(a, b)
这些是我机器上的结果:
# Short list:
compare_bitwise took 10.145 ms
compare_listcomp took 11.157 ms
compare_intersect took 7.461 ms
# Long list:
compare_bitwise took 11203.709 ms
compare_listcomp took 17361.736 ms
compare_intersect took 6833.768 ms
显然,任何人为的性能测试都应该慎重考虑,但由于set().intersection()
的答案至少与其他解决方案一样快,而且可读性最强,因此它应该成为这个常见问题的标准解决方案。
【讨论】:
Set 实际上是在删除重复,所以在我的情况下不会工作 @rgralma 从现有的list
中创建一个新的set
不会从原始list
中删除任何内容。如果您需要特殊逻辑来处理列表中的重复项,我认为您需要提出一个新问题,因为答案需要具体说明您希望如何处理重复项。【参考方案4】:
我更喜欢基于集合的答案,但这是一个无论如何都有效的答案
[x for x in a if x in b]
【讨论】:
【参考方案5】:快捷方式:
list(set(a).intersection(set(b)))
【讨论】:
【参考方案6】:最简单的方法是使用sets:
>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
set([5])
【讨论】:
【参考方案7】:>>> s = ['a','b','c']
>>> f = ['a','b','d','c']
>>> ss= set(s)
>>> fs =set(f)
>>> print ss.intersection(fs)
**set(['a', 'c', 'b'])**
>>> print ss.union(fs)
**set(['a', 'c', 'b', 'd'])**
>>> print ss.union(fs) - ss.intersection(fs)
**set(['d'])**
【讨论】:
接受的答案不适用于包含字符串的列表。这个可以。【参考方案8】:您也可以尝试这样做,方法是将常用元素保留在新列表中。
new_list = []
for element in a:
if element in b:
new_list.append(element)
【讨论】:
【参考方案9】:另一种更实用的方法来检查列表 1 (lst1) 和列表 2 (lst2) 的列表相等性,其中对象的深度为 1 并且保持顺序是:
all(i == j for i, j in zip(lst1, lst2))
【讨论】:
【参考方案10】:你想要重复吗?如果不是,也许您应该改用集合:
>>> set([1, 2, 3, 4, 5]).intersection(set([9, 8, 7, 6, 5]))
set([5])
【讨论】:
如果你真的想要列表,java2s.com/Code/Python/List/Functiontointersecttwolists.htm >>> intersect([1, 2, 3, 4, 5], [9, 8, 7, 6, 5]) [5] 根据文档 - ... 排除了容易出错的结构,如 Set('abc') & 'cbs' 支持更具可读性的 Set('abc').intersection( 'cbs')。 - docs.python.org/library/sets.html【参考方案11】:也可以使用 itertools.product。
>>> common_elements=[]
>>> for i in list(itertools.product(a,b)):
... if i[0] == i[1]:
... common_elements.append(i[0])
【讨论】:
【参考方案12】:你可以使用
def returnMatches(a,b):
return list(set(a) & set(b))
【讨论】:
【参考方案13】:你可以使用:
a = [1, 3, 4, 5, 9, 6, 7, 8]
b = [1, 7, 0, 9]
same_values = set(a) & set(b)
print same_values
输出:
set([1, 7, 9])
【讨论】:
这与 6 多年前接受的答案有何不同? 好吧,我用输出写了完整的细节,对初学者 python 有好处【参考方案14】:如果你想要一个布尔值:
>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(b) == set(a) & set(b) and set(a) == set(a) & set(b)
False
>>> a = [3,1,2]
>>> b = [1,2,3]
>>> set(b) == set(a) & set(b) and set(a) == set(a) & set(b)
True
【讨论】:
【参考方案15】:a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
lista =set(a)
listb =set(b)
print listb.intersection(lista)
returnMatches = set(['5']) #output
print " ".join(str(return) for return in returnMatches ) # remove the set()
5 #final output
【讨论】:
虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高答案的长期价值。【参考方案16】:使用__and__
属性方法也可以。
>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a).__and__(set(b))
set([5])
或者干脆
>>> set([1, 2, 3, 4, 5]).__and__(set([9, 8, 7, 6, 5]))
set([5])
>>>
【讨论】:
【参考方案17】:以下解决方案适用于任何顺序的列表项,并且还支持两个列表的长度不同。
import numpy as np
def getMatches(a, b):
matches = []
unique_a = np.unique(a)
unique_b = np.unique(b)
for a in unique_a:
for b in unique_b:
if a == b:
matches.append(a)
return matches
print(getMatches([1, 2, 3, 4, 5], [9, 8, 7, 6, 5, 9])) # displays [5]
print(getMatches([1, 2, 3], [3, 4, 5, 1])) # displays [1, 3]
【讨论】:
Numpy 有一个特定的功能:np.intersect1d(list1, list2)
【参考方案18】:
我刚刚使用了以下内容,它对我有用:
group1 = [1, 2, 3, 4, 5]
group2 = [9, 8, 7, 6, 5]
for k in group1:
for v in group2:
if k == v:
print(k)
这将在您的情况下打印 5 。不过,性能可能不是很好。
【讨论】:
【参考方案19】:you can | for set union and & for set intersection.
for example:
set1=1,2,3
set2=3,4,5
print(set1&set2)
output=3
set1=1,2,3
set2=3,4,5
print(set1|set2)
output=1,2,3,4,5
curly braces in the answer.
【讨论】:
问题是列表而不是集合。在片场使用&
运算符已经是 SilentGhost 在接受的答案中的答案【参考方案20】:
这适用于可能返回某个字符串或输出的人, 这是代码,希望对您有所帮助:
lis =[]
#convert to list
a = list(data)
b = list(data)
def make_list():
c = "greater than"
d = "less_than"
e = "equal"
for first, first_te in zip(a, b):
if first < first_te:
lis.append(d)
elif first > first_te:
lis.append(c)
else:
lis.append(e)
return lis
make_list()
【讨论】:
【参考方案21】:另一种找到共同值的方法:
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
matches = [i for i in a if i in b]
【讨论】:
以上是关于如何比较python中的两个列表并返回匹配项的主要内容,如果未能解决你的问题,请参考以下文章