【问题标题】:Remove unique tuples from a list of tuples in python从python中的元组列表中删除唯一的元组
【发布时间】:2017-10-09 06:23:03
【问题描述】:

我正在编写一个查找重复文件的程序,现在我有一个元组列表

mylist = [(file1, size1, hash1),
          (file2, size2, hash2),
          ...
          (fileN, sizeN, hashN)]

我想删除具有唯一哈希的条目,只留下重复项。我正在使用

def dropunique(mylist):
templist = []
while mylist:
    mycandidate = mylist.pop()
    templist.append([mycandidate])
    for myfile in mylist:
        if myfile[-1] == mycandidate[-1]:
            templist[-1].append(myfile)
            mylist.remove(myfile)
for myfile in templist:
    if len(myfile) != 1:
        mylist.append(myfile)
templist = [item for sublist in mylist for item in sublist]
return templist

在我弹出一个条目的地方,查看是否有其他条目具有相同的散列和组,然后在具有相同散列的列表列表中。然后,我只使用 len > 1 的子列表创建另一个列表,并将结果列表扁平化为一个简单列表。 我的问题是,当我在某些列表上使用“for myfile in mylist:”时从列表中删除一个条目时,它会跳过相同的条目并在后面继续存在。

【问题讨论】:

  • 在遍历列表时删除项目类似于在地球构造板块快速移动时跳跃。
  • 请不要使用list 作为变量名,因为您会隐藏list 类型。例如,替换为my_list

标签: python algorithm duplicates tuples uniqueidentifier


【解决方案1】:

将您的列表复制到以哈希为键的字典中,然后在第二次通过时删除具有单个计数的列表 - 您甚至可以使用 collections.Counter 来节省一两行代码:

from collections import Counter

counter = Counter(t[2] for t in list_)

result = [value for value in list_ if counter[value[2]] > 1]

(非相关提示:避免将变量命名为“list”或“dict” - 这会覆盖这些变量的 Python 默认内置函数)

【讨论】:

  • 这个{t[2]: t for t in list_} 会丢弃重复项。
【解决方案2】:

我会使用defaultdict() 将元组按其哈希值分组:

from collections import defaultdict

# Group the tuples by their hashvalues
d = defaultdict(list)
for tup in data:
    filename, size, hashvalue = tup
    d[hash].append(tup)

# Display groups of tuples that have more than one tuple
for hashvalue, tuples in d.items():
    if len(tuples) > 1:
        print('Tuples with %r in common' % hashvalue)
        for tup in tuples:
            print(tup)
        print()

【讨论】:

    【解决方案3】:

    使用 groupby 的解决方案

    from itertools import groupby
    
    my_list = [(1, 2, 3),
               (1, 2, 3),
               (4, 5, 6)]
    
    
    vals = []
    
    for hash_val, items in groupby(sorted(my_list), hash):
        results = tuple(items)
        if len(results) > 1:
            vals.append(results[0])
    

    【讨论】:

    • 不能保证他们的列表是预先排序的,所以groupby 不会像我们预期的那样组成整个组
    • 需要更像这样:key_fn = operator.itemgetter(1) 其中1 是“哈希”的索引,然后是itertools.groupby(sorted(items, key=key_fn), key_fn)
    【解决方案4】:

    您可以像这样使用双 filter

    filter(lambda el: len(filter(lambda item: item[2] == el[2], my_list)) > 1, my_list)
    

    结果:

    >>> my_list = [('file1', 'size1', 'hash1'), ('file2', 'size2', 'hash2'), ('file3', 'size3', 'hash3'), ('file4', 'size4', 'hash2')]
    >>>
    >>> filter(lambda el: len(filter(lambda item: item[2] == el[2], my_list)) > 1, my_list)
    [('file2', 'size2', 'hash2'), ('file4', 'size4', 'hash2')]
    

    请注意,在 Python 3 中,filter 返回一个迭代器,因此您需要将其转换为如下列表:list(filter(...))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-25
      • 2012-03-30
      相关资源
      最近更新 更多