【问题标题】:Finding matching and nonmatching items in lists在列表中查找匹配项和不匹配项
【发布时间】:2012-01-22 11:21:06
【问题描述】:

我对 Python 还是很陌生,对列表可以做什么和不能做什么有点困惑。我有两个列表要比较并以二进制格式返回匹配和不匹配的元素。 List1 的长度不变,而List2 的长度不同(但总是比List1 短)。

例如:

List1 = ['dog', 'cat', 'pig', 'donkey']
List2 = ['dog', 'cat', 'donkey']

想要的输出:

List3 = [1, 1, 0, 1]

我目前的代码是:

def match_nonmatch(List1, List2):
    List3 = []
    for i in range(len(List1)):
        for j in range(len(List2)):
            if List1[i] == List2[j]:
                List3.append(1)
            else:
                List3.append(0)
   return List3

当我比较列表时,我能够返回匹配项,但是当我包含上面显示的 else 语句以返回不匹配项时,我最终得到的列表比它应该的要长得多。例如,当我使用一个比较 60 个项目的列表时,我得到一个包含 3600 个项目而不是 60 个项目的列表。

如果有人能向我解释我的代码目前存在的问题并建议我如何修改代码以使其达到我想要的效果,我将不胜感激。

【问题讨论】:

    标签: python


    【解决方案1】:

    你也可以使用按位运算:

    List1 = ['dog', 'cat', 'pig', 'donkey']  
    List2 = ['dog', 'cat', 'donkey']  
    

    匹配:

    set(List1) & set(List2)   
    

    不匹配:

    set(List1) ^ set(List2) 
    

    【讨论】:

      【解决方案2】:

      使用set 而不是list。这样你可以做很多好事:

      set1 = set(['dog', 'cat', 'pig', 'donkey'])
      set2 = set(['dog', 'cat', 'donkey'])
      
      matched = set1.intersection(set2) # set(['dog', 'cat', 'donkey'])
      unmatched = set1.symmetric_difference(set2) # set(['pig'])
      

      我知道这并不完全符合您的要求,但在执行此类操作时,使用集合而不是列表通常是一种更好的做法。

      更多关于套装的信息:http://docs.python.org/library/stdtypes.html#set

      【讨论】:

      • 感谢套装的链接。之前没有遇到过这个概念,所以会读一读。
      【解决方案3】:

      使用以下代码。

      listt3=[]
      
      for i in listt1:
          if i in listt2:
              listt3.append(1)
          else:
              listt3.append(0)
      

      如果你更喜欢单行,

      listt3=[ 1 if i in listt2 else 0 for i in listt1]

      【讨论】:

      • @Srinivas 和鸭嘴兽:你不认为这不会给出所需的确切输出吗?应该将 listt1 和 listt2 交换为确切的输出。
      • @Srinivas Anytime... 此代码可以更好地转换为单行代码listt3=[int(i in listt2) for i in listt1]
      • 是的,同意,但 OP 是 python 的新手。 :)
      • @SandipAgarwal 更好的是listt3=[ 1 if i in listt2 else 0 for i in listt1]....现在快乐吗? :)
      • @Srinivas 嘿,那真的好多了。它甚至没有击中我。谢谢。 :D
      【解决方案4】:

      如果list2 很短,我会这样做:

      list1 = ['dog', 'cat', 'pig', 'donkey']
      list2 = ['dog', 'cat', 'donkey']
      list3 = [int(val in list2) for val in list1]
      print(list3)
      

      打印出来:

      [1, 1, 0, 1]
      

      如果list2 很长,可以先将其转换为set,以提高代码效率:

      list1 = ['dog', 'cat', 'pig', 'donkey']
      set2 = set(['dog', 'cat', 'donkey'])
      list3 = [int(val in set2) for val in list1]
      print(list3)
      

      您当前代码产生过多元素的原因是您在内循环的每次迭代中都调用了append(),并且有len(List1) * len(List2) 这样的迭代。

      解决方法如下:

      def match_nonmatch(List1, List2):
          List3 = []
          for i in range(len(List1)):
              for j in range(len(List2)):
                  if List1[i] == List2[j]:
                      List3.append(1)
                      break             # fix #1
              else:                     # fix #2
                  List3.append(0)
          return List3
      

      注意添加的break 以及else 子句现在指的是内部for 而不是if

      也就是说,我仍然会在答案的顶部使用单行。

      【讨论】:

      • 感谢您的解释。在阅读了这个和其他回复之后,我会研究一下集合 - 以前没有遇到过这个概念。
      • @aix 你不认为else 语句的行会出现错误吗?
      • @SandipAgarwal:不,我不知道。我在发布之前测试了代码并且它有效。 for...else 是 Python 中的有效构造 -- 查一下。
      • @aix 嘿,它有效。我这边有些问题。你不觉得写单行字更好吗?
      • @SandipAgarwal:我愿意。看我回答的最后一句话。
      【解决方案5】:
      >>> list1 = ['dog', 'cat', 'pig', 'donkey']; list2 = ['dog', 'cat', 'donkey']
      >>> [i in list2 for i in list1]
      [True, True, False, True]
      

      另外,您应该阅读 PEP8,CamelCase 名称通常仅用于类。

      【讨论】:

        【解决方案6】:
        [int(i==j) for i, j in zip(list1, list2)]
        

        【讨论】:

        • 欢迎来到 Stack Overflow!感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation would greatly improve its long-term value 通过展示为什么这是一个很好的解决问题的方法,并将使其对未来有其他类似问题的读者更有用。请edit您的回答添加一些解释,包括您所做的假设。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-31
        • 2020-07-31
        相关资源
        最近更新 更多