我一直在解决这个问题...我有一个简化的数据集,如:
dict = {'A': [('a', 1, 1), ('b', 2, 2), ('c', 3, 3)], 'B': [('b', 2, 2), ('a', 1, 1)], 'C': [('d', 4, 4)], 'D': [('c', 3, 3), ('e', 5, 5)]}
其中值表示元组列表。
我需要找到字典中的每个值,是否是在另一个值中找到的列表元素?如果是,则应从字典中删除键值对。例如,[(' b',2,2),(' a',1,1)]可以在[(' a',1, 1),(' b',2,2),(' c',3,3)],因此' B'的关键值对应该删除。最终字典应如下所示:
dict = {'A': [('a', 1, 1), ('b', 2, 2), ('c', 3, 3)], 'C': [('d', 4, 4)], 'D': [('c', 3, 3), ('e', 5, 5)]}
我搜索了论坛,但没有找到解决这个问题的方法...非常感谢任何帮助!谢谢!
此字典不包含重复值,因为我之前通过根据另一组条件映射到另一个字典来删除它们。但是,如果解决方案也可以扩展到重复项,则可能对其他人有用,例如保留所有重复项中的1个。
PS:感谢所有回复!
答案 0 :(得分:0)
您可以使用sets检查一个值是否包含在一起(set.issubset(otherset)
)。
以下代码演示了如何轻松实现此功能。对于每个值,检查每个其他值是否包含在内。这可以肯定地进行优化。
# input data
d = {'A': [('a', 1, 1), ('b', 2, 2), ('c', 3, 3)], 'B': [('b', 2, 2), ('a', 1, 1)], 'C': [('d', 4, 4)]}
# convert each value to a set
ds = { k: frozenset(v) for k,v in d.items() }
# filter out contained values
keys = [ k1 for k1,v1 in ds.items() if [k2 for k2,v2 in ds.items() if v1.issubset(v2)] == [k1] ]
# map filtered keys to original dict
df = dict(zip(keys, map(d.get, keys)))
# df = {'A': [('a', 1, 1), ('b', 2, 2), ('c', 3, 3)], 'C': [('d', 4, 4)]}
为每对keys
计算(k1,v1)
时,完成以下操作。
所有其他对(k2,v2)
(包括(k1,v1)
)都会针对v1.issubset(v2)
进行检查。对于满足此条件的所有对,记录密钥(k2
)并将其存储在列表中。如果其他值没有包含我们的给定值v1
,则此列表将仅包含k1
,因为issubset
关系是自反的(v.issubset(v)
总是True
)。因此,当返回的列表正好是[k1]
时,我们没问题。
如果列表包含的值多于k1
,则v1
包含在某个其他值中,必须进行过滤。
没有为地图中的重复值定义问题。我的解决方案跟踪原始密钥,因此对于重复值,两个对都被丢弃。您还可以在此处介绍自定义行为,例如只保留最小的'所有重复的关键。
其他解决方案保留所有对,因此返回的映射仍包含重复值。
此keys
的修改版本可以处理上述情况:
keys = [ k1 for k1,v1 in ds.items()
if not any(v1 < v2 for v2 in ds.values())
and k1 == min(k2 for k2,v2 in ds.items() if v1 == v2) ]
答案 1 :(得分:0)
您可以将值转换为frozensets集,然后过滤掉重复项,最后选择值在集合中的字典项:
d = {
'A': [('a', 1, 1), ('b', 2, 2), ('c', 3, 3)],
'B': [('b', 2, 2), ('a', 1, 1)],
'C': [('d', 4, 4)]
}
sets = {frozenset(v) for v in d.values()}
sets = {s for s in sets if not any(s < s2 for s2 in sets)}
res = {k: v for k, v in d.items() if set(v) in sets} # {'A': [('a', 1, 1), ('b', 2, 2), ('c', 3, 3)], 'C': [('d', 4, 4)]}
答案 2 :(得分:0)
使用set
和combinations
:
from itertools import combinations
d = {'A': [('a', 1, 1), ('b', 2, 2), ('c', 3, 3)], 'B': [('b', 2, 2), ('a', 1, 1)], 'C': [('d', 4, 4)]}
xs = set()
for (ai, av), (bi, bv) in combinations(d.items(), 2):
if set(av) <= set(bv): xs.add(ai)
if set(bv) <= set(av): xs.add(bi)
for x in xs: del d[x]
print d
# {'A': [('a', 1, 1), ('b', 2, 2), ('c', 3, 3)], 'C': [('d', 4, 4)]}