【问题标题】:Comparing two lists and only printing the differences? (XORing two lists)比较两个列表并只打印差异? (异或两个列表)
【发布时间】:2013-04-25 03:08:51
【问题描述】:

我正在尝试创建一个函数,该函数接受 2 个列表并返回仅具有两个列表差异的列表。

例子:

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

结果应该打印[4,5,7,8]

目前的功能:

def xor(list1, list2):
    list3=list1+list2
    for i in range(0, len(list3)):
        x=list3[i]
        y=i
        while y>0 and x<list3[y-1]:
            list3[y]=list3[y-1]
            y=y-1
        list3[y]=x

        last=list3[-1]
    for i in range(len(list3) -2, -1, -1):
        if last==list3[i]:
            del list3[i]
        else:
            last=list3[i]

    return list3 
print xor([1,2,5,7,8],[1,2,4,8,9])

第一个 for 循环对其进行排序,第二个循环删除重复项。问题是结果是 [1,2,4,5,7,8,9] 不是 [4,5,7,8],所以它不会完全删除重复项?我可以添加什么来做到这一点。 我不能使用任何特殊的模块,.sort、set 或任何东西,基本上只是循环。

【问题讨论】:

    标签: python python-2.7


    【解决方案1】:

    您基本上想将一个元素添加到您的新列表中,如果它存在于一个列表中而不存在于另一个列表中。这是一个可以做到的紧凑循环。对于两个列表中的每个元素(将它们与list1+list2 连接),如果其中一个不存在,我们添加元素:

    [a for a in list1+list2 if (a not in list1) or (a not in list2)]
    

    您可以像现在一样通过显式循环元素轻松地将其转换为更非 Pythonic 的代码,但老实说,我没有看到任何意义(并不重要):

    def xor(list1, list2):
        outputlist = []
        list3 = list1 + list2
        for i in range(0, len(list3)):
            if ((list3[i] not in list1) or (list3[i] not in list2)) and (list3[i] not in outputlist):
                 outputlist[len(outputlist):] = [list3[i]]
        return outputlist
    

    【讨论】:

    • 我想我明白它在做什么,但是我如何将它变成一个完整的循环并将这个循环添加到原始函数中,或者它会自己工作......
    • 这是一个执行您正在创建的功能的单线...您遍历 list1+list2 元素 x 并有两个 if:1. 如果 list1 中的元素,使 flag1=True,2 . 如果 list2 中有元素,则使 flag2=True;如果 (flag1 and flag2) != True 并且 x 不在 outputlist 中,则将其添加到 outputlist。
    • @user2314520 sashkello 的意思是任何列表推导都等效于对可迭代项的for 循环,如果它们符合条件,则将所述项目添加到新列表中,然后使用结果列表。
    • @user2314520,我添加了一个长版本。
    • @user2314520:另一种看待它的方式是:它找到两个列表的并集,而不包括列表的交集(即,它找到symmetric difference)。联合是list1 + list2。如果xlist1 中并且xlist2 中,则元素x 在交集中;您想排除此类元素,因此应颠倒条件:not (x in list1 and x in list2) 相当于x not in list1 or x not in list2。把它们放在一起xor_list = [x for x in (list1 + list2) if x not in list1 or x not in list2]
    【解决方案2】:

    使用集合更好

    >>> a = [1,2,5,7,9]
    >>> b = [1,2,4,8,9]
    >>> set(a).symmetric_difference(b)
    {4, 5, 7, 8}
    

    感谢@DSM,更好的句子是:

    >>> set(a)^set(b)
    

    这两种说法是一样的。但后者更清楚。

    更新:抱歉,我没有看到最后一个要求:不能使用 set。在我看来,@sashkello 提供的解决方案是最好的。

    【讨论】:

    • 非家庭作业的好答案,但是'我不能使用任何特殊模块,.sort、set 或任何东西,基本上只是循环。'
    • 如果我们使用集合,为什么不直接使用 set(a) ^ set(b)
    • @DSM 谢谢,你的建议更好。我只是忘记了语法。
    • 其实我喜欢symmetric_difference^ 一样多,但我更喜欢你原来的长版本。但是你在我评论的同时把它改成了symmetric_difference。 :^)
    • @Sheng 的更新,我们可以通过简单的 list(set(a)^set(b)) 将其转换为列表 # 返回一个列表
    【解决方案3】:

    注意:这真的很不合Python,只能用作作业答案:)

    对两个列表进行排序后,您可以通过执行以下操作来查找重复项:

    1) 将迭代器放在 A 和 B 的开头

    2)如果Aitr大于Bitr,将Bitr的值放入返回列表后推进Bitr

    3) 否则如果Bitr大于Aitr,将Aitr的值放入返回列表后推进Aiter

    4) 否则你找到了重复的,提前 Aitr 和 Bitr

    【讨论】:

    • 为什么你认为你的方法是非pythonic?
    • @gnibbler 查看盛对我认为是 pythonic 的回答
    • 这依赖于所有可散列的元素。 (他们可能是)
    【解决方案4】:

    假设您有已排序的列表,则此代码有效。它在线性时间内起作用,而不是像许多其他给出的解决方案那样是二次的。

    def diff(sl0, sl1):
        i0, i1 = 0, 0
        while i0 < len(sl0) and i1 < len(sl1):
            if sl0[i0] == sl1[i1]:
                i0 += 1
                i1 += 1
            elif sl0[i0] < sl1[i1]:
                yield sl0[i0]
                i0 += 1
            else:
                yield sl1[i1]
                i1 += 1
        for i in xrange(i0, len(sl0)):
            yield sl0[i]
        for i in xrange(i1, len(sl1)):
            yield sl1[i]
    
    print list(diff([1,2,5,7,9], [1,2,4,8,9]))
    

    【讨论】:

    【解决方案5】:

    试试这个,

        a = [1,2,5,7,9]
        b = [1,2,4,8,9]
     print set(a).symmetric_difference(set(b))
    

    【讨论】:

      【解决方案6】:

      简单,但不是特别有效:)

      >>> a = [1,2,5,7,9]
      >>> b = [1,2,4,8,9]
      >>> [i for i in a+b if (a+b).count(i)==1]
      [5, 7, 4, 8]
      

      或者用“只是循环”

      >>> res = []
      >>> for i in a+b:
      ...  c = 0
      ...  for j in a+b:
      ...   if i==j:
      ...    c += 1
      ...  if c == 1:
      ...   res.append(i)
      ... 
      >>> res
      [5, 7, 4, 8]
      

      【讨论】:

        猜你喜欢
        • 2019-05-15
        • 1970-01-01
        • 1970-01-01
        • 2014-02-26
        • 1970-01-01
        • 1970-01-01
        • 2019-08-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多