如何比较python中的列表/集列表?

时间:2011-05-24 04:46:59

标签: python list compare set tuples

比较2个列表/集合并输出差异的最简单方法是什么?是否有任何内置函数可以帮助我比较嵌套列表/集合?

输入:

First_list = [['Test.doc', '1a1a1a', 1111], 
              ['Test2.doc', '2b2b2b', 2222],  
              ['Test3.doc', '3c3c3c', 3333]
             ]  
Secnd_list = [['Test.doc', '1a1a1a', 1111], 
              ['Test2.doc', '2b2b2b', 2222], 
              ['Test3.doc', '8p8p8p', 9999], 
              ['Test4.doc', '4d4d4d', 4444]]  

预期产出:

Differences = [['Test3.doc', '3c3c3c', 3333],
               ['Test3.doc', '8p8p8p', 9999], 
               ['Test4.doc', '4d4d4d', 4444]]

8 个答案:

答案 0 :(得分:31)

所以你想要两个项目列表之间的区别。

first_list = [['Test.doc', '1a1a1a', 1111], 
              ['Test2.doc', '2b2b2b', 2222], 
              ['Test3.doc', '3c3c3c', 3333]]
secnd_list = [['Test.doc', '1a1a1a', 1111], 
              ['Test2.doc', '2b2b2b', 2222], 
              ['Test3.doc', '8p8p8p', 9999], 
              ['Test4.doc', '4d4d4d', 4444]]

首先,我将每个列表列表转换为元组列表,因为元组是可清除的(列表不是),因此您可以将元组列表转换为一组元组:

first_tuple_list = [tuple(lst) for lst in first_list]
secnd_tuple_list = [tuple(lst) for lst in secnd_list]

然后你可以制作套装:

first_set = set(first_tuple_list)
secnd_set = set(secnd_tuple_list)

编辑(由sdolan建议):你可以在一行中为每个列表完成最后两个步骤:

first_set = set(map(tuple, first_list))
secnd_set = set(map(tuple, secnd_list))

注意:map是一个函数式编程命令,它将第一个参数中的函数(在本例中为tuple函数)应用于第二个参数中的每个项目(在我们的示例中是一个列表)列表)。

找到集合之间的对称差异:

>>> first_set.symmetric_difference(secnd_set) 
set([('Test3.doc', '3c3c3c', 3333),
     ('Test3.doc', '8p8p8p', 9999),
     ('Test4.doc', '4d4d4d', 4444)])

注意first_set ^ secnd_set相当于symmetric_difference

此外,如果您不想使用集合(例如,使用python 2.2),那么它非常简单。例如,列表推导:

>>> [x for x in first_list if x not in secnd_list] + [x for x in secnd_list if x not in first_list]
[['Test3.doc', '3c3c3c', 3333],
 ['Test3.doc', '8p8p8p', 9999],
 ['Test4.doc', '4d4d4d', 4444]]

或使用功能filter命令和lambda函数。 (你必须测试两种方式并结合起来)。

>>> filter(lambda x: x not in secnd_list, first_list) + filter(lambda x: x not in first_list, secnd_list)

[['Test3.doc', '3c3c3c', 3333],
 ['Test3.doc', '8p8p8p', 9999],
 ['Test4.doc', '4d4d4d', 4444]]

答案 1 :(得分:3)

不确定是否有一个很好的功能,但“手动”的方式并不困难:

differences = []

for list in firstList:
    if list not in secondList:
        differences.append(list)

答案 2 :(得分:2)

>>> First_list = [['Test.doc', '1a1a1a', '1111'], ['Test2.doc', '2b2b2b', '2222'], ['Test3.doc', '3c3c3c', '3333']] 
>>> Secnd_list = [['Test.doc', '1a1a1a', '1111'], ['Test2.doc', '2b2b2b', '2222'], ['Test3.doc', '3c3c3c', '3333'], ['Test4.doc', '4d4d4d', '4444']] 


>>> z = [tuple(y) for y in First_list]
>>> z
[('Test.doc', '1a1a1a', '1111'), ('Test2.doc', '2b2b2b', '2222'), ('Test3.doc', '3c3c3c', '3333')]
>>> x = [tuple(y) for y in Secnd_list]
>>> x
[('Test.doc', '1a1a1a', '1111'), ('Test2.doc', '2b2b2b', '2222'), ('Test3.doc', '3c3c3c', '3333'), ('Test4.doc', '4d4d4d', '4444')]


>>> set(x) - set(z)
set([('Test4.doc', '4d4d4d', '4444')])

答案 3 :(得分:1)

我猜您必须将列表转换为集合:

>>> a = {('a', 'b'), ('c', 'd'), ('e', 'f')}
>>> b = {('a', 'b'), ('h', 'g')}
>>> a.symmetric_difference(b)
{('e', 'f'), ('h', 'g'), ('c', 'd')}

答案 4 :(得分:1)

一个老问题,但这是我用来返回两个列表中未找到的唯一元素的解决方案。

我用它来比较数据库返回的值和目录搜寻器程序包生成的值。我不喜欢找到的其他解决方案,因为其中许多解决方案无法动态处理平面列表和嵌套列表。

List.tabulate(10)(_ => makeRandomPerson())

答案 5 :(得分:0)

http://docs.python.org/library/difflib.html是您正在寻找的好地方。

如果以递归方式将其应用于增量,则应该能够处理嵌套数据结构。但这需要一些工作。

答案 6 :(得分:0)

通过使用集合理解,您可以使其成为一个单行。如果你想:

得到一组元组,然后:

Differences = {tuple(i) for i in First_list} ^ {tuple(i) for i in Secnd_list}

或者获取元组列表,然后:

Differences = list({tuple(i) for i in First_list} ^ {tuple(i) for i in Secnd_list})

或者获取列表列表(如果你真的想要),那么:

Differences = [list(j) for j in {tuple(i) for i in First_list} ^ {tuple(i) for i in Secnd_list}]

PS:我在这里读到:https://stackoverflow.com/a/10973817/4900095 map()函数不是pythonic的做事方式。

答案 7 :(得分:0)

请注意,使用这种方法,您将失去订单

first_set=set(map(tuple,S))
second_set=set(map(tuple,T))
print map(list,list(first_set.union(second_set)-(first_set&second_set)))