Python 移除合并字典列表中的重复值

3 投票
4 回答
7858 浏览
提问于 2025-04-17 15:12

我需要一点作业帮助。我得写一个函数,把几个字典合并成一个新的字典。如果一个键出现多次,那么在新字典中对应这个键的值应该是一个独特的列表。下面是我目前的代码:

f = {'a': 'apple', 'c': 'cat', 'b': 'bat', 'd': 'dog'}
g =  {'c': 'car', 'b': 'bat', 'e': 'elephant'}
h = {'b': 'boy', 'd': 'deer'}
r = {'a': 'adam'}

def merge(*d):
    newdicts={}
    for dict in d:
        for k in dict.items():
            if k[0] in newdicts:
                newdicts[k[0]].append(k[1])
            else:
                newdicts[k[0]]=[k[1]]
    return newdicts

combined = merge(f, g, h, r)
print(combined)

输出结果看起来是这样的:

{'a': ['apple', 'adam'], 'c': ['cat', 'car'], 'b': ['bat', 'bat', 'boy'], 'e': ['elephant'], 'd': ['dog', 'deer']}

在'b'这个键下,'bat'出现了两次。我该怎么去掉重复的呢?

我查过filter和lambda,但不知道怎么用(可能是因为它是在字典里的列表?)

任何帮助都非常感谢!提前谢谢大家的帮助!

4 个回答

1

在你的for循环里加上这个:

for dict in d:
    for k in dict.items():
        if k[0] in newdicts:
            # This line below
            if k[1] not in newdicts[k[0]]:
                newdicts[k[0]].append(k[1])
        else:
            newdicts[k[0]]=[k[1]]

这样可以确保不会添加重复的内容。

2
>>> import collections
>>> import itertools
>>> uniques = collections.defaultdict(set)
>>> for k, v in itertools.chain(f.items(), g.items(), h.items(), r.items()):
...   uniques[k].add(v)
... 
>>> uniques
defaultdict(<type 'set'>, {'a': set(['apple', 'adam']), 'c': set(['car', 'cat']), 'b':        set(['boy', 'bat']), 'e': set(['elephant']), 'd': set(['deer', 'dog'])})

注意,这里的结果是用集合(set)表示的,而不是用列表(list)。这样做在计算上要高效得多。如果你想要最后的结果是列表形式,可以这样做:

>>> {x: list(y) for x, y in uniques.items()}

{'a': ['apple', 'adam'], 'c': ['car', 'cat'], 'b': ['boy', 'bat'], 'e': ['elephant'], 'd': ['deer', 'dog']}

5

在把元素添加到列表之前,先检查一下这个元素是否已经在列表里。

for k in dict.items():
    if k[0] in newdicts:
        if k[1] not in newdicts[k[0]]:  # Do this test before adding.
            newdicts[k[0]].append(k[1])
    else:
        newdicts[k[0]]=[k[1]]

因为你想要的value列表里只有独一无二的元素,所以可以直接用Set来代替它。此外,你还可以使用defaultdict,这样在添加元素之前就不用检查这个键是否存在了。

另外,不要用内置的名称作为你的变量名,比如不要用dict,换成其他的名字会更好。

所以,你可以把你的merge方法修改成这样:

from collections import defaultdict

def merge(*d):
    newdicts = defaultdict(set)  # Define a defaultdict
    for each_dict in d:

        # dict.items() returns a list of (k, v) tuple.
        # So, you can directly unpack the tuple in two loop variables.
        for k, v in each_dict.items():  
            newdicts[k].add(v)

    # And if you want the exact representation that you have shown   
    # You can build a normal dict out of your newly built dict.
    unique = {key: list(value) for key, value in newdicts.items()}
    return unique

撰写回答