【问题标题】:How can I compare two lists in python and return matches如何比较python中的两个列表并返回匹配项
【发布时间】:2010-11-26 04:56:20
【问题描述】:

我想获取两个列表并找到两个列表中出现的值。

a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]

returnMatches(a, b)

例如会返回[5]

【问题讨论】:

  • 下面的答案对我来说似乎都是错误的。如果一个数字在任一列表中重复会发生什么,您肯定想知道 (?)(例如,说两个列表都有两次“5”)任何使用集合的解决方案都会立即删除所有重复的项目,你会输那个信息。

标签: python list


【解决方案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 TrueFalse
  • 这个答案更加灵活易读,因为人们可能需要differenceunion
  • 如果我有对象作为列表元素并且只想要部分匹配,即只有一些属性必须匹配才能被视为匹配对象?
  • .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])
            

            【讨论】:

            【解决方案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]
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2020-12-19
                          • 1970-01-01
                          • 2016-12-23
                          • 2021-09-19
                          • 1970-01-01
                          • 1970-01-01
                          • 2012-05-09
                          • 2017-10-28
                          相关资源
                          最近更新 更多