2010-08-04 138 views
3

一个字典python dict通过键值去除重复值?

dic = { 
1: 'a', 
2: 'a', 
3: 'b', 
4: 'a', 
5: 'c', 
6: 'd', 
7: 'd', 
8: 'a', 
9: 'a'} 

我想删除重复的值只是保持一个K/V对, 关于“键”选择那些重复值的,其可以是最大或最小或通过随机选择其中的一个重复项目的关键。

我不想使用k/v交换,因为它无法控制密钥选择。

采取值 “a”,例如

1: 'a', 
2: 'a', 
4: 'a', 
8: 'a', 
9: 'a' 

最大关键将是{9: 'A'}和最小将是{1: 'A'},以及随机会的choise任一项的。

而且,如果关键字是其他类型的可哈希值,例如string,那么如何做这样的选择?

任何人都可以分享我的想法吗?

谢谢!

+0

你可以翻转它,让键是值,反之亦然? – sas4740 2010-08-04 03:25:21

+0

OP确实说过“我不想使用ak/v swap,因为它无法控制密钥选择” - 模糊,但我认为这意味着值可能是列表,字典或其他不可接受的对象作为关键。 – 2010-08-04 05:29:32

回答

2
import itertools as it 

newdic = {} 
for v, grp in it.groupby(sorted((v, k) for k, v in dic.items)): 
    newdic[min(k for _, k in grp)] = v 

或其他“选择”,以代替min功能(其中,当然,也做工精细,即使键是字符串 - 会给你在这种情况下,“词汇第一”键)。

选择函数需要注意的一种情况是,对应于相同值的键可能是不可比较的(例如,复数,或者在Python 3中,不同非全部数字类型的对象)。 min中的key=不会治愈;-)。

+0

谢谢亚历克斯,我仍然在试图找出如何随机选择重复的密钥在你的方式。 – 2010-08-04 09:14:46

+0

@KC,'random.choice(list(grp))[1]'是最简单的(当然有算法具有更好的big-O用于此目的,但除非您的重复密钥组成长成多个每个键的数千个案例;-)。 – 2010-08-04 16:48:32

1

这会给你一个随机选择的唯一密钥:

In [29]: dic 
Out[29]: {1: 'a', 2: 'a', 3: 'b', 4: 'a', 5: 'c', 6: 'd', 7: 'd', 8: 'a', 9: 'a'} 

In [30]: dict((v,k) for k,v in dic.iteritems()) 
Out[30]: {'a': 9, 'b': 3, 'c': 5, 'd': 7} 

In [31]: dict((v,k) for k,v in dict((v,k) for k,v in dic.iteritems()).iteritems()) 
Out[31]: {3: 'b', 5: 'c', 7: 'd', 9: 'a'} 
+1

你能解释一下它为什么i​​teritem随机返回 – 2010-08-04 04:06:55

+0

@注册:Python的字典是无序的。因此,从dic.iteritems()发出键值对的顺序是未确定的。我应该说“未定”而不是“随机”。 – unutbu 2010-08-04 10:58:28

+0

@Registered:我错过了一个事实,即您请求的方法不使用键值交换。对不起 - 这正是我上面做的。我会留下来让你阅读,然后在一天左右删除。 – unutbu 2010-08-04 11:04:42

5

你可以建立一个反向字典,其中值是从初始字典中所有键的列表。使用这个,你可以做你想要的,min,max,random,alternate min和max,或者其他。

from collections import defaultdict 

d = defaultdict(list) 
for k,v in dic.iteritems(): 
    d[v].append(k) 

print d 
# {'a': [1, 2, 4, 8, 9], 'c': [5], 'b': [3], 'd': [6, 7]} 
+0

很容易理解那些值可哈希,谢谢! – 2010-08-04 09:23:16