2012-04-05 26 views
1

我想将键更改为python字典中的值,但原始字典中的值不唯一。当值不是唯一的时,在python字典中转置值和键

以下是我有:

year_person = {2000: ‘Linda’, 2001: ‘Ron’, 2002: ‘Bruce’, 2003: ‘Linda’, 2004: ‘Bruce’, 2005 ‘Gary’, 2006: ‘Linda’} 

这是我想将它更改为:

person_year = {‘Linda’: 2000, ‘Ron’: 2001, ‘Bruce’: 2002, ‘Linda’, 2003: ‘Bruce’, 2004 ‘Gary’, 2005: ‘Linda’: 2006} 

当我试图用它来转换一个for循环,我只得到了一个匹配为每个人配对。

+3

你不能那样做。每个密钥必须是唯一的。您可以创建每个键的所有值的列表。 – alan 2012-04-05 22:16:14

+2

rel:http://stackoverflow.com/q/483666/989121 – georg 2012-04-05 22:16:44

回答

2

你想达到的目标在技术上是不可行的。字典的关键字不能重复,因为如果是这样的话,你不能唯一索引一个带有关键字的字典。

你可以做的是创建一个(键,值)对的字典,其中value是具有相同键的所有项目的列表。为了实现它,你可以做一些事情如下

>>> person_year={} 
>>> [person_year.setdefault(v,[]).append(k) for (k,v) in year_person.iteritems()] 
[None, None, None, None, None, None, None] 
>>> person_year 
{'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]} 
>>> 

注意,如果你只在键值对感兴趣,而不是一本字典本身”你可以存储为元组的列表如下

>>> [(v,k) for k,v in year_person.iteritems()] 
[('Linda', 2000), ('Ron', 2001), ('Bruce', 2002), ('Linda', 2003), ('Bruce', 2004), ('Gary', 2005), ('Linda', 2006)] 
>>> 
+1

我将其描述为unpythonic - 列表理解旨在用于创建列表,而不是处理数据。在这种情况下,一个更清晰,更清晰的解决方案是alan给出的defaultdict。另外值得注意的是''iteritems()''只存在Python 3.0以前的版本,之后只需使用''items()''。 – 2012-04-05 22:49:55

8

你也可以用defaultdict做到这一点:

year_person = {2000: 'Linda', 2001: 'Ron', 2002: 'Bruce', 2003: 'Linda', 2004: 'Bruce', 2005: 'Gary', 2006: 'Linda'} 

from collections import defaultdict 
d = defaultdict(list) 
for k, v in year_person.items(): 
    d[v].append(k) 

print dict(d) 
>>> {'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]} 
+3

如果有人要使用'defaultdict',那么当实现此功能的函数返回时,它应该转换为常规的'dict'。 'defaultdict'具有隐式地将错过的属性命中转换为插入的烦人特性。即当这不是你想要的时候它会产生错误。 – aaronasterling 2012-04-06 16:37:19

+0

是的,这就是为什么我将它转换为'print'语句。 – alan 2012-04-06 16:44:38

+3

这是说明潜在问题的不完全透明的方式。 – aaronasterling 2012-04-06 16:48:19

3

只是提出一些其他的选择和信息可能会从目前的答案会丢失:

如果您确定您的值是唯一的,因此可以成为关键,最简单的方法是一个字典理解:

year_person = {2000: 'Linda', 2001: 'Ron', 2002: 'Bruce', 2003: 'Linda', 2004: 'Bruce', 2005: 'Gary', 2006: 'Linda'} 
person_year = {key: value for (value, key) in year_person.items()} 

当然,你的情况,他们都没有,所以这是行不通(因为它仅给出了最后的价值发现):

person_year = {'Bruce': 2004, 'Linda': 2006, 'Ron': 2001, 'Gary': 2005} 

相反,我们可以使用嵌套表补偿的字典里面补偿:

{key: [value for value, check_key in year_person.items() if check_key==key] for key in year_person.values()} 

给我们:

{'Bruce': [2002, 2004], 'Linda': [2000, 2003, 2006], 'Ron': [2001], 'Gary': [2005]} 

这个工作,但效率不高,因为必须遍历每个条目的整个词典。一个更好的解决方案是由alan给出的the defaultdict solution,它只需要一个循环。

2

IMO,defaultdict在这里是不必要的,并且将其作为列表理解来牺牲可读性(尽管通常情况并非如此)。除非分析表明,这的确是一个瓶颈,我会如下做到这一点:

def invert_to_lists(dct): 
    inverted_dict = {} 
    for key in dct: 
     inverted_dict.setdefault(dct[key], []).append(key) 
    return inverted_dict 

defaultdict是一个更复杂。在这种情况下使用setdefault是很好的,因为它只需要输入一次。在完成导入和实例化defaultdict之后,您将输入的内容多于拨打setdefault

+0

那么问题是什么?为什么downvote? – aaronasterling 2012-04-05 23:57:28

相关问题