2010-01-12 6 views
27

다 대다 상관 관계가있는 튜플 전체를 살펴보고 각 (a, b)의 b에 b에 해당하는 모든 a의 목록이있는 사전을 만들고 싶습니다. 사전의 key b에있는리스트를 테스트하고, a를 찾은 다음, 이미 존재하지 않는다면 a를 추가하고, 튜플 소화 루프를 통해 모든 시간을 매기는 것은 어색합니다. 그러나 나는 아직 더 좋은 길을 찾지 못했습니다. 존재하나요? 이 일을하는 다른 방법이 훨씬 더 예쁘습니까?목록을 만들거나 이미 존재하는 경우 목록에 추가하는 효율적인 방법은 무엇입니까?

+1

을 사용할 수 있습니다 또는 알고리즘 적으로? –

답변

36

setdefault() 방법에 대한 the docs를 참조하십시오

을 setDefault (키 [기본])
키의 값을 반환, 사전에 경우입니다. 그렇지 않은 경우 값의 키를 삽입하고 기본값을 반환합니다. 기본값 의 기본값은 없음입니다.

당신은 존재하거나 이미 존재하지 않는 경우는, 하늘의 목록에 b를 설정하면 b를 얻을 것이다 단일 통화로 사용할 수 있습니다 - 그리고 어느 쪽이든, 반환 B :

>>> key = 'b' 
>>> val = 'a' 
>>> print d 
{} 
>>> d.setdefault(key, []).append(val) 
>>> print d 
{'b': ['a']} 
>>> d.setdefault(key, []).append('zee') 
>>> print d 
{'b': ['a', 'zee']} 

당신이 세 줄에 계신 확인 "가 아닌"단순한 이것을 결합하고 당신이 한 :

>>> b = d.setdefault('b', []) 
>>> if val not in b: 
... b.append(val) 
... 
>>> print d 
{'b': ['a', 'zee', 'c']} 
+3

'defaultdict'는 파이썬 2.5 이상을 가지고 있다고 가정하고'setdefault'보다 조금 더 멋집니다. – ephemient

+1

나는 2.34와 붙어있다. 그래서 이것은 실제로 대답이다. 나에게 감사한다, 제임스! – user249228

+5

D' oh. 'set()'은 훌륭하지만 2.4까지 내장되어 있지 않습니다. 파이썬이 왜 그렇게 오래 되었습니까? :-( – ephemient

2

당신이 당신의 튜플 O를 정렬 할 수 있습니다 다음 사전 O (N)을 생성 (N 로그 n)

또는 더 간단하게 O (N) 그러나 많은 튜플의 경우 메모리에 부하를 부과 할 수있다 :

your_dict = {} 
for (a,b) in your_list: 
    if b in your_dict: 
     your_dict[b].append(a) 
    else: 
     your_dict[b]=[a] 

흠 당신이 묘사 한 것과 거의 비슷합니다. 그것에 대해 어색한 무엇입니까?

더러운 작업을 수행하기 위해 SQL 데이터베이스를 사용할 수도 있습니다.

+0

더 간단한 방법은 O (n)입니다. 그렇기 때문에 튜플 방법을 정렬하는 것이 좋습니다. – kennytm

+0

예, 편집 된 버전에서도 언급했습니다. –

+0

downvoting에 대한 의견이 있으십니까? –

0

난 당신이 키 테스트 나가 얼마나 잘 모르겠지만, 그들은 키/값 쌍은 초기화되고 나면 쉽게 :

d = {} 
if 'b' not in d: 
    d['b'] = set() 
d['b'].add('a') 

세트가 보장됩니다 만 1 '은 그 '이 (가) 컬렉션에 있습니다. 키/값이 존재하는지 확인하기 위해 초기 'b'체크를해야합니다.

+0

호기심 왜 -1일까요? 어떻게 든 잘못 됐니? 나는 그것이 틀린 경우에 대답을 삭제할 것이다. –

15

당신이 정말로 목록에 연결하지 않는 가정, defaultdictset은 매우 편리합니다.

import collections 
d = collections.defaultdict(set) 
for a, b in mappings: 
    d[b].add(a) 

당신 정말 대신 세트의 목록을 원하는 경우에, 당신은

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

와이에 따라 수 있습니다 그리고 당신은 정말 대신 defaultdict의 DICT을 원한다면, 당신은

을 말할 수있다
d = dict(d) 

나는 당신이하고 싶은 어떤 이유인지 정말로 모르지만.

+0

아아, 그렇습니다. 값이 없으면 초기 검사를합니다. 감사합니다. 새로운 것을 배웠습니다. :) –

+1

+ 1 'defaultdict'는 실제로 가장 Pythonic 솔루션이기 때문에 +1합니다. – jathanism

+1

나는이 사람이 내가 defaultdict (lambda : defaultdict (list))를 찾도록 도왔다. (http://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html) – lkraav

4

컬렉션을 사용하십시오.대신 if를 사용

your_dict = defaultdict(list) 
for (a,b) in your_list: 
    your_dict[b].append(a) 
+0

'추가 '? – interjay

+0

예, 그랬습니다. 감사합니다 –

+0

OP의 "then a not already there"는 원래 목록에 중복이있을 수 있다고 생각하게 만듭니다. 따라서 필자는'list' 대신'set'을 사용했습니다. – ephemient

3

을 defaultdict, AFAIK는 파이썬 더 대신 try 블록을 사용하는 것이다.

your_list=[('a',1),('a',3),('b',1),('f',1),('a',2),('z',1)] 

your_dict={} 
for (a,b) in your_list: 
    try: 
     your_dict[b].append(a) 
    except KeyError: 
     your_dict[b]=[a] 

print your_dict 
0

dict get 방법? 이 some_key가 사전에있는 경우 my_dict[some_key]의 값을 반환하고, 그렇지 않은 경우 - (아래의 예에서 []) 일부 기본 값을 반환합니다 :

my_dict[some_key] = my_dict.get(some_key, []).append(something_else) 
0

는 (같은하지만 어쩌면 효율적이지 않고 효율적 또 다른 방법있다 세트) 및 간단합니다. 실제로는 defaultdict과 유사하지만 추가 가져 오기가 필요하지 않습니다. 비어있는 (없음) 키가있는 딕트를 사용하면 딕셔너리 키를 어딘가에 만들 수 있음을 의미합니다. dict.fromkeys 메서드로 그렇게 할 수 있으며이 메서드를 사용하면 모든 키에 기본값을 설정할 수 있습니다. result 될 것

keylist = ['key1', 'key2'] 
result = dict.fromkeys(keylist, []) 

: { '키 1'[] '키 2': []}

그런 다음 당신은 당신의 루프를 수행하고 구문 의미 예뻐으로 result['key1'].append(..) 직접

관련 문제