Python中检查字典中列表中的重复元素

4
我是一个有用的助手,可以翻译文本。
我有一个字典,其中可能有多达N个键,并附加到每个键的列表。我需要检查一个列表中的唯一元素,以及字典中所有其他列表中的元素是否相同。
字典结构的示例:
dict = {'N1': ['e1', 'e2', ...], 'N2': ['e1', 'e3', ...], 'N...': [....], ....}

我需要将它们附加到另一个字典下相同的键名中,但只包含列表中的唯一元素。
return_dict = {'N1': ['e2'], 'N2': ['e3'], 'N...': [...], ...}

我希望这里的信息足够让人理解我的问题。如果有人能帮助我找到一种简便的方法来做到这一点,那将不胜感激。

编辑:今天也没有方便的导入。:(

3个回答

2

如果不涉及导入(叹气)的解决方案,我们首先通过列出每个值所在的列表来“反转”字典:

d = {'N1': ['e1', 'e2'], 'N2': ['e1', 'e3']}

inverse = {item: [key for key,ls in d.items() if item in ls]
           for item in set(sum(d.values(),[]))
          }

在我们的情况下,inverse 现在是 {'e1': ['N1', 'N2'], 'e3': ['N2'], 'e2': ['N1']}。现在我们只需要再次“反转”这个字典,确保忽略重复项。
ret = {key: [item for item in count if key in count[item] and len(count[item]) == 1]
       for key in set(sum(count.values(),[]))
       }

ret 然后是 {'N1': ['e2'], 'N2': ['e3']}


其中最有趣的部分可能是将 itertools.chain.from_iterable 重新实现为 lambda x: sum(x, []):不太常用的 sum 函数的第二个参数允许你设置一个起始值,由于你可以将列表 "相加",这将获取一系列列表并制作一个新的大列表。


这对我来说几乎可以工作,唯一的问题是它看到的第一个元素,如果它实际上是重复的,它将不知道并将计算为唯一。 - Kezaraux
@Kezaraux 你的意思是列表本身包含重复项吗?我在编辑中使用了d[key]上的set来解决这个问题。 - L3viathan
当我运行它时,我的return_dict中得到了{'N2': ['e3', 'e1'], 'N1': ['e2']},而我期望的是{'N2': ['e3'], 'N1': ['e2']} - Kezaraux
哦...我意识到我误解了你的任务。我以为你想要去重列表,而不是在发现重复项时删除所有副本。我明天会修复它。 - L3viathan
没关系。我想我可能本可以更好地表达我的问题。不过还是谢谢你帮助我。非常感激。 - Kezaraux
@Kezaraux 我修改了我的答案,以符合你的问题。 - L3viathan

1

首先,需要注意的是,应避免使用 dict 作为变量名,因为会掩盖内置类型的名称。

现在,如果我理解你的问题正确,这个代码应该可以满足你的要求:

from collections import Counter
d = {'N1': ['e1', 'e2'], 'N2': ['e1', 'e3']}
# Copy the dictionary if you want to keep the original one. Note in particular
# that `return_dict = dict(d)` will not be sufficient as we need a deep copy
return_dict = {k: list(v) for k, v in d.items()}
# Count the occurrences of list elements
counts = Counter([a for v in return_dict.values() for a in v])
# Remove elements that appear more than once
for v in return_dict.values():
    for a in v:
        if counts[a] > 1:
            v.remove(a)
print(d)  # Prints {'N2': ['e1', 'e3'], 'N1': ['e1', 'e2']}
print(return_dict)   # Prints {'N1': ['e2'], 'N2': ['e3']}

非常抱歉,我忘了提到我不能使用任何导入。否则这是一个对我很有效的好方案!只需要绕过那个不允许导入的限制。 - Kezaraux
1
你可以使用copy模块来复制一个字典(浅层或深层)。 - syedelec
@Kezaraux 然后实现一个 Counter。这很简单,这个解决方案实际上是伪代码。我们不是来为你做作业的。无论如何,你已经得到了答案。 - juanpa.arrivillaga

0
好的,从L3viathan的回答开始,我开始尝试类似的方法。这可能会非常粗糙和可怕,但它适合我的需求。我发现有效的方法是:
ret = {}
seen = set()
repeated = set()
for key in hash_dict:
    for item in hash_dict[key]:
        if item in seen:
            repeated.add(item)
        else:
            seen.add(item)
for key in hash_dict:
    ret[key] = ret.get(key, [])
    for item in hash_dict[key]:
        if item not in repeated:
            ret[key].append(item)
return ret

在我看来,这看起来非常混乱,但由于我对Python的知识不够广泛,并且受到不能使用导入的限制,这就是我所能做的。

编辑:变量名称不同是因为我直接从正在进行的项目中复制了它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接