如何从 python 中的 defaultdict(int) 中删除重复值?
How to remove duplicate values from defaultdict(int) in python?
我有一个字典,它由如下唯一的键值对组成:
edu_bg={1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2}
我想根据以上数据创建一个字典,以便将相似的记录(具有相似的值)分组如下:
{(1, 3): 1, (5, 6): 1, (1, 4): 1, (2, 6): 1,(2, 5): 1, (3, 4): 1})
我尝试使用以下代码实现上述输出:
myedu = defaultdict(int)
for k,v in edu_bg.iteritems():
for K,V in edu_bg.iteritems():
if K == k and V == v:
pass
if K != k and V == v:
myedu[(k,K)] += 1
else:
pass
然而却导致重复记录如下:
defaultdict(<type 'int'>, {(1, 3): 1, (5, 6): 1, (4, 1): 1, (3, 1): 1, (5, 2): 1, (1, 4): 1, (2, 6): 1, (4, 3): 1, (6, 2): 1, (2, 5): 1, (3, 4): 1, (6, 5): 1})
我想删除这些重复值。对此问题的任何建议表示赞赏。
您正在将每个键与所有其他键(包括它们自己)进行比较。这些导致 n**2 检查,包括您不想考虑的两种情况:键与自身比较和键比较两次。您已经正确传递了键相等的情况。您可以传递键 k
小于键 K
的情况,这将忽略本应重复的一半检查。
from collections import defaultdict
edu_bg = {1:1, 2:2, 3:1, 4:1, 5:2, 6:2}
myedu = defaultdict(int)
for k,v in edu_bg.iteritems():
for K,V in edu_bg.iteritems():
if K == k and V == v:
pass
if K > k and V == v:
myedu[(k,K)] += 1
else:
pass
print myedu
理想情况下,您会限制 for
循环,这样密钥被同等或两次计算的情况就永远不会发生。您可以通过以下方式进行操作:
edu_bg = {1:1, 2:2, 3:1, 4:1, 5:2, 6:2}
myedu = defaultdict(int)
keys = edu_bg.keys()
for i in xrange(len(keys)):
for j in xrange(i+1, len(keys)):
k = keys[i]
K = keys[j]
if edu_bg[k] == edu_bg[K]:
myedu[(k,K)] += 1
print myedu
不是迭代每对的笛卡尔积,这将迭代恰好 n^2 个元素,您可以迭代每个可能的组合,这将迭代 n(n-1)/2 个元素。虽然 Big Oh 复杂度相同,但常数因子将显着降低:
>>> from collections import defaultdict
>>> from itertools import combinations
>>> myedu = defaultdict(int)
>>> edu_bg={1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2}
>>> for k1,k2 in combinations(edu_bg,2):
... if edu_bg[k1] == edu_bg[k2]:
... myedu[(k1,k2)] += 1
...
>>> myedu
defaultdict(<class 'int'>, {(2, 6): 1, (1, 3): 1, (5, 6): 1, (2, 5): 1, (3, 4): 1, (1, 4): 1})
>>>
不过我要重申一下,这听起来像是 XY problem...
反转映射并获取按值划分的键组的组合。
>>> edu_bg={1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2}
>>> def invert(d):
... i={}
... for k,v in d.iteritems():
... i.setdefault(v,[]).append(k)
... return i
...
>>> invert(edu_bg)
{1: [1, 3, 4], 2: [2, 5, 6]}
然后为每个子列表计算 combinations(sublist, 2)
:
>>> [comb for sublist in {1: [1, 3, 4], 2: [2, 5, 6]}.values() for comb in combinations(sublist, 2)]
[(1, 3), (1, 4), (3, 4), (2, 5), (2, 6), (5, 6)]
所有计数将始终为 1,因为每个组合只生成一次。
因此,我们可以简单地生成请求的输出:
>>> dict.fromkeys([(1, 3), (1, 4), (3, 4), (2, 5), (2, 6), (5, 6)], 1)
{(2, 6): 1, (5, 6): 1, (1, 4): 1, (1, 3): 1, (2, 5): 1, (3, 4): 1}
每一步合并
>>> dict.fromkeys([comb for sublist in invert(edu_bg).values() for comb in combinations(sublist, 2)],1)
{(2, 6): 1, (5, 6): 1, (1, 4): 1, (1, 3): 1, (2, 5): 1, (3, 4): 1}
这比迭代产品或组合和过滤的成本要低得多。这也会生成所有没有重复的输出。
我有一个字典,它由如下唯一的键值对组成:
edu_bg={1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2}
我想根据以上数据创建一个字典,以便将相似的记录(具有相似的值)分组如下:
{(1, 3): 1, (5, 6): 1, (1, 4): 1, (2, 6): 1,(2, 5): 1, (3, 4): 1})
我尝试使用以下代码实现上述输出:
myedu = defaultdict(int)
for k,v in edu_bg.iteritems():
for K,V in edu_bg.iteritems():
if K == k and V == v:
pass
if K != k and V == v:
myedu[(k,K)] += 1
else:
pass
然而却导致重复记录如下:
defaultdict(<type 'int'>, {(1, 3): 1, (5, 6): 1, (4, 1): 1, (3, 1): 1, (5, 2): 1, (1, 4): 1, (2, 6): 1, (4, 3): 1, (6, 2): 1, (2, 5): 1, (3, 4): 1, (6, 5): 1})
我想删除这些重复值。对此问题的任何建议表示赞赏。
您正在将每个键与所有其他键(包括它们自己)进行比较。这些导致 n**2 检查,包括您不想考虑的两种情况:键与自身比较和键比较两次。您已经正确传递了键相等的情况。您可以传递键 k
小于键 K
的情况,这将忽略本应重复的一半检查。
from collections import defaultdict
edu_bg = {1:1, 2:2, 3:1, 4:1, 5:2, 6:2}
myedu = defaultdict(int)
for k,v in edu_bg.iteritems():
for K,V in edu_bg.iteritems():
if K == k and V == v:
pass
if K > k and V == v:
myedu[(k,K)] += 1
else:
pass
print myedu
理想情况下,您会限制 for
循环,这样密钥被同等或两次计算的情况就永远不会发生。您可以通过以下方式进行操作:
edu_bg = {1:1, 2:2, 3:1, 4:1, 5:2, 6:2}
myedu = defaultdict(int)
keys = edu_bg.keys()
for i in xrange(len(keys)):
for j in xrange(i+1, len(keys)):
k = keys[i]
K = keys[j]
if edu_bg[k] == edu_bg[K]:
myedu[(k,K)] += 1
print myedu
不是迭代每对的笛卡尔积,这将迭代恰好 n^2 个元素,您可以迭代每个可能的组合,这将迭代 n(n-1)/2 个元素。虽然 Big Oh 复杂度相同,但常数因子将显着降低:
>>> from collections import defaultdict
>>> from itertools import combinations
>>> myedu = defaultdict(int)
>>> edu_bg={1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2}
>>> for k1,k2 in combinations(edu_bg,2):
... if edu_bg[k1] == edu_bg[k2]:
... myedu[(k1,k2)] += 1
...
>>> myedu
defaultdict(<class 'int'>, {(2, 6): 1, (1, 3): 1, (5, 6): 1, (2, 5): 1, (3, 4): 1, (1, 4): 1})
>>>
不过我要重申一下,这听起来像是 XY problem...
反转映射并获取按值划分的键组的组合。
>>> edu_bg={1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2}
>>> def invert(d):
... i={}
... for k,v in d.iteritems():
... i.setdefault(v,[]).append(k)
... return i
...
>>> invert(edu_bg)
{1: [1, 3, 4], 2: [2, 5, 6]}
然后为每个子列表计算 combinations(sublist, 2)
:
>>> [comb for sublist in {1: [1, 3, 4], 2: [2, 5, 6]}.values() for comb in combinations(sublist, 2)]
[(1, 3), (1, 4), (3, 4), (2, 5), (2, 6), (5, 6)]
所有计数将始终为 1,因为每个组合只生成一次。 因此,我们可以简单地生成请求的输出:
>>> dict.fromkeys([(1, 3), (1, 4), (3, 4), (2, 5), (2, 6), (5, 6)], 1)
{(2, 6): 1, (5, 6): 1, (1, 4): 1, (1, 3): 1, (2, 5): 1, (3, 4): 1}
每一步合并
>>> dict.fromkeys([comb for sublist in invert(edu_bg).values() for comb in combinations(sublist, 2)],1)
{(2, 6): 1, (5, 6): 1, (1, 4): 1, (1, 3): 1, (2, 5): 1, (3, 4): 1}
这比迭代产品或组合和过滤的成本要低得多。这也会生成所有没有重复的输出。