所以我正在研究这个简单的程序,以检查两个列表中是否有共同的元素 因此我编写的代码使用了if嵌套,但我想知道有没有比嵌套格式更好的方法呢?
def common_data(list1, list2):
result = False
for x in list1:
for y in list2:
if x == y:
result = True
return result
还有没有办法检查n个列表中的公共元素?
答案 0 :(得分:3)
您可以使用any
遍历一个列表,然后检查另一个列表中的包含。这样的好处是在找到第一个包含的元素时会发生短路。
>>> a = [1,2,3,4]
>>> b = [4,5,6,7]
>>> any(i in b for i in a)
True
或者,您可以检查两个列表之间的set.intersection
的大小
>>> a = [1,2,3,4]
>>> b = [4,5,6,7]
>>> len(set(a).intersection(b)) > 0
True
答案 1 :(得分:1)
第一个选项最简单。您想知道列表2中是否有列表1中的任何元素。生成器理解力几乎可以将英语概念直接转化为代码。对于大型列表而言,这种方法效率低下,但是编码起来非常容易。
result = any(x in list2 for x in list1)
如果您的元素是可哈希的,则可以通过将集合用于O(1)包含查找来改进它。请注意,我们只想从最小的列表中创建一个集合,以最大程度地减少额外的内存并为该操作工作,并且我们使用内置的any()
使其短路并在我们立即找到一个list2中的项目。
if len(list1) > len(list2):
list1, list2 = list2, list1
cache = set(list1)
result = any(x in cache for x in list2)
如果您的元素不可散列且不可排序,另一种选择是对两个列表进行排序,合并并检查重复项(至关重要的是,这是一个与您的相等性定义相匹配的完整顺序-当元素不同时,一个应该小于另一个)。
值得注意的是,由于所有其他元组,这具有相当高的对象创建开销。可能需要编写自己的例程来逐步浏览两个排序的列表,并跟踪上一个元素来自哪个列表,而不是调用heapq.merge()
。
import heapq
list1, list2, prev, result = sorted(list1), sorted(list2), None, False
for item, i in heapq.merge(
((x, 1) for x in list1),
((x, 2) for x in list2)):
if prev and item==prev[0] and i!=prev[1]:
result = True
break
prev = (item, i)
还可能值得注意的是,如果您唯一可用的操作是相等性测试(对象不可排序,不可哈希等),则通常无法将len(list1)的最坏情况提高到O(nm)以上)== n和len(list2)== m。仍然有一个有趣的特殊情况(例如,如果唯一元素的数量很少),但是如果您没有有关该问题的其他信息,那么您将比天真的解决方案做得更好。
答案 2 :(得分:1)
如果元素是可哈希的...
更短的表情
>>> list1 = [1, 2, 3]
>>> list2 = [2, 3, 4]
>>> bool(set(list1) & set(list2))
True
对于您的“ n个列表”问题:
>>> lists = [[1, 2, 3, 4, 5],
[2, 3, 4, 5, 6],
[3, 4, 5, 6, 7],
[4, 5, 6, 7, 8]]
>>> bool(set(lists[0]).intersection(*lists))
True
当然,如果您只是打算在bool
之类的布尔上下文中使用它,或者如果您确实想了解公共元素,则可能不需要显式转换为if ... :
。
>>> if set(list1) & set(list2):
print('common!')
common!
>>> set(list1) & set(list2)
{2, 3}
>>> set(lists[0]).intersection(*lists)
{4, 5}