我有一个 python 字典,其中包含一些示例键和值:
{'a': ['b'],
'c': ['d'],
'x': ['y'],
'y': ['x'],
'i': ['j','k'],
'j': ['i','k']
'k': ['i','j']}
键是什么字母以及值是哪个字母是无关紧要的,只要它们被证明有关系。我需要能够删除任何“重复”键值组合,以便我的字典显示如下。
{'a': ['b'],
'c': ['d'],
'x': ['y'],
'i': ['j','k']}
您可以将每个条目转换为排序的
tuple
并使用 set
来获取 O(d * vlog(v) )
时间,其中 d
是字典中键的数量,v
是值的长度。 vlog(v
用于对每行需要完成的元组进行排序。
d = {'a': ['b'],
'c': ['d'],
'x': ['y'],
'y': ['x'],
'i': ['j','k'],
'j': ['i','k'],
'k': ['i','j']}
seen = set()
to_remove = []
for key, val in d.items():
entry = tuple(sorted(val.copy() + [key]))
to_remove.append(key) if entry in seen else seen.add(entry)
for key in to_remove:
del d[key]
print(d)
输出:
{'a': ['b'], 'c': ['d'], 'x': ['y'], 'i': ['j', 'k']}
这是一种解决方案,如何将它放在一个循环中,并将字典理解作为单行:
{k: v for i, (k, v) in enumerate(d.items()) if not set(list(d.keys())[:i]).intersection(v)}
如果你想很快得到它:
s = set()
dmod = {}
for k, v in d.items():
s.add(k)
if not s.intersection(v):
dmod[k] = v
两种方法都假设你的字典名为
d
。# {'a': ['b'], 'c': ['d'], 'x': ['y'], 'i': ['j', 'k']}
但是,我必须在这里声明,您的文字描述不符合预期的示例。如果能更新一下就好了
除此之外:您是否知道您要求的算法完全依赖于顺序?在 python 3.6 之前,如果不明确使用有序字典,没有任何解决方案可以返回您想要的结果可靠地工作。
我不知道你的用例,但是将相同的算法应用于例如可以吗?向后排序的字典会产生不同的结果吗?
另一内衬:
>>> d = {'a': ['b'], 'c': ['d'], 'x': ['y'], 'y': ['x'], 'i': ['j','k'], 'j': ['i','k'], 'k': ['i','j']}
>>> dict({tuple(sorted((k, *v))):(k, v) for k, v in d.items()}.values())
{'a': ['b'], 'c': ['d'], 'y': ['x'], 'k': ['i', 'j']}
内部字典是用sorted元组
(key, value1, value2, ...)
作为键和(key, [value1, value2, ...])
对作为值构建的。显然,对于每个排序的元组,您保留最后一个 (key, [value])
对(仅当 dict 键已排序时这才重要,Python >= 3.6)。然后用这些 (key, [value])
对构建一个字典。
如果只想获取第一个
key-value
(Python >= 3.6),只需颠倒原始字典的迭代顺序即可:
>>> dict({tuple(sorted((k, *v))):(k, v) for k, v in sorted(d.items(), reverse=True)}.values())
{'x': ['y'], 'i': ['j', 'k'], 'c': ['d'], 'a': ['b']}
如果还不清楚,这里有一个更简单的例子。我想在列表中保留具有给定长度的第一个列表:
>>> L = [[1], [2], [1,2], [2,3,4], [3], [5,2], [7,8,9]]
>>> {len(v): v for v in reversed(L)}
{3: [2, 3, 4], 2: [1, 2], 1: [1]}
我们看到只保留了第一个值:
[*[1]*, [2], *[1,2]*, *[2,3,4]*, [3], [5,2], [7,8,9]]
因为第一个值是最后一个添加到字典中的值,并覆盖下一个值(或按相反顺序覆盖前一个值)。