Pythonic方式比较两个列表并打印不匹配的项目?

时间:2010-08-19 20:58:59

标签: python list

我有两个字典的Python列表,entries9entries10。我想比较项目并将联合项目写入名为joint_items的新列表。我还想将不匹配的项目保存到两个新列表unmatched_items_9unmatched_items_10

这是我的代码。获取joint_itemsunmatched_items_9(在外部列表中)非常简单:但如何获取unmatched_items_10(在内部列表中)?

for counter, entry1 in enumerate(entries9):
    match_found = False
    for counter2,entry2 in enumerate(entries10):
        if match_found:
            continue
        if entry1[a]==entry2[a] and entry1[b]==entry2[b]: # the dictionaries only have some keys in common, but we care about a and b
            match_found = True
            joint_item = entry1
            joint_items.append(joint_item)
            #entries10.remove(entry2) # Tried this originally, but realised it messes with the original list object!
    if match_found:
        continue
    else: 
        unmatched_items_9.append(entry1)

性能不是真正的问题,因为它是一个一次性的脚本。

3 个答案:

答案 0 :(得分:8)

相当于你现在正在做的事情,但反过来说,是:

unmatched_items_10 = [d for d in entries10 if d not in entries9]

虽然比编码方式更简洁,但它具有相同的性能问题:它需要时间与每个列表中的项目数成比例。如果你感兴趣的长度大约是9或10(正如这些数字似乎表明的那样),没问题。

但是对于相当长的列表,你可以通过对列表进行排序并“并行”“并行”来获得更好的性能,可以这么说(时间与N log N成正比,其中N是长度更长的清单)。还有其他可能性(增加复杂性;-)即使这种更高级的方法不足以为您提供所需的性能。除非你表明你确实要求它获得良好的性能,否则我将避免提出非常复杂的内容(在这种情况下,请提及每个列表的典型长度这些代码的典型内容他们的项目,当然,这些“细节”是 选择算法的关键考虑因素,这是速度和简单性之间的良好折衷。)

编辑:OP编辑了他的Q以显示他关心的内容,对于任何两个词组d1d2来自两个列表,不是{是{ {1}}(这是d1 == d2运算符检查的内容),而是in。在这种情况下,d1[a]==d2[a] and d1[b]==d2[b]运算符不能被使用(好吧,不是没有一些时髦的包装,但这是一个在可行时最好避免的并发症;-),但是in内置函数可以轻松地替换它:

all

由于我们希望匹配的词组,我已经切换了逻辑(到unmatched_items_10 = [d for d in entries10 if all(d[a]!=d1[a] or d[b]!=d2[b] for d2 in entries9)] !=,每De Morgan's laws)。但是,如果您愿意:

or

就个人而言,我不喜欢unmatched_items_10 = [d for d in entries10 if not any(d[a]==d1[a] and d[b]==d2[b] for d2 in entries9)] if not any,因为文体原因,但数学是无可挑剔的(维基百科页面称之为Extensions至De Morgan的定律,因为if not all是一个存在量词,any是一个通用量词,可以这么说;-)。性能应该大致相当(但是,OP在评论中明确表示,在这项任务中,性能对他们来说并不是非常重要)。

答案 1 :(得分:0)

Python stdlib有一个类difflib.SequenceMatcher,看起来它可以做你想要的,虽然我不知道如何使用它!

答案 2 :(得分:0)

您可以考虑使用sets及其相关方法,例如intersection。但是,您需要将字典转换为不可变数据,以便将它们存储在set(例如string s)中。这样的事情会起作用吗?

a = set(str(x) for x in entries9)
b = set(str(x) for x in entries10)  

# You'll have to change the above lines if you only care about _some_ of the keys

joint_items = a.union(b)
unmatched_items = a - b

# Now you can turn them back into dicts:
joint_items     = [eval(i) for i in joint_items]
unmatched_items = [eval(i) for i in unmatched_items]