Python 去除字典中一个键的重复值

Python remove duplicate values of one key in dict

我有这样一本字典:

Files:
{'key1': ['path1', 'path1', 'path2', 'path1', 'path2'], 
'key2': ['f', 'f', 'f', 'f', 'f'], 
'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']}

我想删除 'key_file' 中的所有重复值和它们在其他键('key1' 和 'key2')中的其他值。

所需词典:

Files:
{'key1': ['path1', 'path2'], 
'key2': ['f', 'f'], 
'key_file': ['file1', 'file2']}

我想不出一个解决方案来保留顺序并删除每个重复项及其在其他键中的值。

非常感谢。

编辑:

'key2': ['f', 'f', 'f', 'f', 'f']

变成

'key2': ['f', 'f'],

因为有两个不同的文件。

我不想删除每个键中的每个重复项。 'path1' 与 'file1' 相关,'path2' 与 'file2' 相关,对于这两种情况,key2 中的 'f' 也是如此。实际上实际上还有几个键,但这是我的最小示例。那是我的问题。我找到了几种删除每个重复项的解决方案。

编辑 2:

也许我有点困惑。

每个键的长度都与描述文件名(在 key_file 中)、相应路径(在 key1 中)和其他一些描述字符串(在 key2 中等)相同。可能会发生同一个文件存储在不同位置(路径)的情况,但我知道,如果文件名完全相同,它就是同一个文件。

基本上我一直在寻找的是一个函数,它检测 key_file 的第二个值,文件名 file1 作为第一个值 file1 的副本,并从每个键中删除第二个值。值编号 4 (file1) 和 5 (file2) 相同。生成的字典看起来就像我提到的那个。

我希望这能更好地解释它。

OrderedDict 是最好的,因为它保留了顺序

您可以将其添加到集合中,然后将其制成列表

例子

for i in d:
    d[i] = list(set(d[i]))

您可以使用 collections.OrderedDict 来保持字典的顺序,并使用 set 来删除重复项:

>>> d={'key1': ['path1', 'path1', 'path2', 'path1', 'path2'], 
... 'key2': ['f', 'f', 'f', 'f', 'f'], 
... 'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']}
>>> from collections import OrderedDict
>>> OrderedDict(sorted([(i,list(set(j))) for i,j in d.items()], key=lambda t: t[0]))
OrderedDict([('key1', ['path2', 'path1']), ('key2', ['f']), ('key_file', ['file2', 'file1'])])

您需要对值使用 set 以删除重复项,然后根据键对您的项目进行排序,最后使用 OrderedDict 使您的字典保持排序。

编辑:如果您希望所有值的长度都与最大值相同,请使用以下内容:

>>> s=sorted([(i,list(set(j))) for i,j in d.items()], key=lambda t: t[0])
>>> M=max(map(len,[i[1] for i in s])
>>> f_s=[(i,j) if len(j)==M else (i,[j[0] for t in range(M)]) for i,j in s]
>>> f_s
[('key1', ['path2', 'path1']), ('key2', ['f', 'f']), ('key_file', ['file2', 'file1'])]
>>> OrderedDict(f_s)
OrderedDict([('key1', ['path2', 'path1']), ('key2', ['f', 'f']), ('key_file', ['file2', 'file1'])])

但如果您只想要任何值的前 2 个元素,您可以使用切片:

>>> OrderedDict(sorted([(i,j[:2]) for i,j in d.items()],key=lambda x: x[0])
... )
OrderedDict([('key1', ['path1', 'path1']), ('key2', ['f', 'f']), ('key_file', ['file1', 'file1'])])

一种天真的方法:遍历键并将每个值添加到新字典:

>>> newFiles={'key1': [], 'key2':[], 'key_file':[]}
>>> for i,j in enumerate(Files['key_file']):
...   if j not in newFiles['key_file']:
...      for key in newFiles.keys():
...         newFiles[key].append(Files[key][i])
...
>>> newFiles
{'key2': ['1', '3'], 'key1': ['a', 'c'], 'key_file': ['file1', 'file2']}

使用 OrderedDict:

>>> for j in OrderedDict.fromkeys(Files['key_file']):
...   i = Files['key_file'].index(j)
...   if j not in newFiles['key_file']:
...     for key in newFiles.keys():
...       newFiles[key].append(Files[key][i])
...
>>> newFiles
{'key2': ['1', '3'], 'key1': ['a', 'c'], 'key_file': ['file1', 'file2']}

注意:如果key_file中的"file"总是有相同的key_1key_2,还有更好的方法。例如使用 zip:

>>> z=zip(*Files.values())
>>> z
[('f', 'path1', 'file1'), ('f', 'path1', 'file1'), ('f', 'path2', 'file2'), ('f', 'path1', 'file1'), ('f', 'path2', 'file2')]
>>> OrderedDict.fromkeys(z)
OrderedDict([(('f', 'path1', 'file1'), None), (('f', 'path2', 'file2'), None)])
>>> list(OrderedDict.fromkeys(z))
[('f', 'path1', 'file1'), ('f', 'path2', 'file2')]
>>> zip(*OrderedDict.fromkeys(z))
[('file1', 'file2'), ('path1', 'path2'), ('f', 'f')]

据我理解这个问题,似乎字典中不同列表中的对应值属于一起,而同一列表中的值彼此无关。在这种情况下,我建议使用不同的数据结构。您可以制作一个包含三元组的列表,而不是使用包含三个项目列表的字典。

>>> files = {'key1': ['path1', 'path1', 'path2', 'path1', 'path2'], 
             'key2': ['f', 'f', 'f', 'f', 'f'], 
             'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']}
>>> files2 = set(zip(files["key1"], files["key2"], files["key_file"]))
>>> print files2
set([('path2', 'f', 'file2'), ('path1', 'f', 'file1')])

或者如果你想让它更像字典,你可以这样做,之后:

>>> files3 = [{"key1": k1, "key2": k2, "key_file": kf} for k1, k2, kf in files2]
>>> print files3
[{'key2': 'f', 'key1': 'path2', 'key_file': 'file2'}, 
 {'key2': 'f', 'key1': 'path1', 'key_file': 'file1'}]

请注意,顶级列表中三元组的顺序可能不同,但属于一起的项目在包含的元组或字典中仍然在一起。

这是我的实现:

In [1]: mydict = {'key1': ['path1', 'path1', 'path2', 'path1', 'path2'], 'key2': ['f', 'f', 'f', 'f', 'f'], 'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']}

In [2]: { k: sorted(list(set(v))) for (k,v) in mydict.iteritems() }
Out[2]: {'key1': ['path1', 'path2'], 'key2': ['f'], 'key_file': ['file1', 'file2']}

测试

In [6]: mydict
Out[6]:
{'key1': ['path1', 'path1', 'path2', 'path1', 'path2'],
 'key2': ['f', 'f', 'f', 'f', 'f'],
 'key_file': ['file1', 'file1', 'file2', 'file1', 'file2']}

In [7]: uniq = { k: sorted(list(set(v))) for (k,v) in mydict.iteritems() }

In [8]: for key in uniq:
   ...:     print 'KEY    :', key
   ...:     print 'VALUE  :', uniq[key]
   ...:     print '-------------------'
   ...: 
KEY    : key2
VALUE  : ['f']
-------------------
KEY    : key1
VALUE  : ['path1', 'path2']
-------------------
KEY    : key_file
VALUE  : ['file1', 'file2']
-------------------