2012-04-05 2 views
1

키를 파이썬 사전에서 값으로 변경하려고하지만 원본 사전의 값이 고유하지 않습니다. 이것은 내가로 변경하고자하는 것입니다값이 고유하지 않은 경우 값과 키를 파이썬 사전에 바꿈

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} 

루프, 나는 단 하나의 일치를 가지고 각 사람을위한 쌍.

+3

당신은 그렇게 할 수 없습니다. 각 키는 고유해야합니다.각 키의 모든 값 목록을 작성할 수 있습니다. – alan

+2

rel : http://stackoverflow.com/q/483666/989121 – georg

답변

2

달성 할 수없는 것은 기술적으로 불가능합니다. 사전에 대한 키는 중복 될 수 없으므로 사전을 키로 고유하게 색인화 할 수 없으므로 중복 될 수 없습니다.

할 수있는 작업은 (key, value) 쌍의 사전을 만드는 것입니다. 여기서 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으로 설명 할 것입니다. 목록 이해는 데이터를 처리하지 않고 목록을 만드는 데 사용하도록 설계되었습니다. 이 경우 훨씬 더 깔끔하고 명확한 해결 방법은 알란이 기본값으로 부여한 것입니다. 또한''iteritems()''는 파이썬 3.x 이전 버전에서만 존재합니다. 그 후에''items()''를 사용하십시오. –

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

+0

네, 그렇기 때문에'print' 문으로 변환했습니다. – alan

+3

그 잠재적 인 문제를 설명하는 정확히 투명하지 않은 방법입니다. – aaronasterling

3

그냥 현재 답변에서 누락 될 수있는 몇 가지 다른 옵션과 정보를 제공하기 위해 :

당신이 당신의 값이 고유 때문에 키가 될 수 있는지 경우 3,516,는, 가장 간단한 방법은 DICT 이해입니다 :

물론
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()} 

, 귀하의 경우, 그렇지 않은, 그래서이 작동하지 않습니다 (이 마지막 값을 제공으로 발견) :

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

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

대신에, 우리는 DICT 빌려 내부에 중첩 된 목록 빌려 사용할 수 있습니다주는 :

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

이 방법은 효과가 있지만 모든 항목에 대해 전체 사전을 반복해야하기 때문에 효율적이지 않습니다. 훨씬 더 좋은 해결책은 앨런에 의해 주어진 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을 가져 와서 인스턴스화하는 rigmarole을 거친 후 setdefault을 호출하는 것 이상을 입력하게됩니다.

+0

그래서 문제가 무엇입니까? 왜 downvote? – aaronasterling

관련 문제