2010-08-19 3 views
2

두 개의 파이썬 사전 목록, entries9entries10이 있습니다. 항목을 비교하고 공동 항목을 joint_items이라는 새 목록에 작성하려고합니다. 또한 일치하지 않는 항목을 unmatched_items_9unmatched_items_10의 두 가지 새 목록에 저장하려고합니다.Pythonic 방식으로 두 목록을 비교하고 비교할 수없는 항목을 인쇄합니까?

이것은 내 코드입니다. joint_itemsunmatched_items_9 (외부 목록에 있음)을 얻는 것은 매우 쉽습니다. 그러나 내부 목록에있는 unmatched_items_10을 얻으려면 어떻게해야합니까?

for counter, entry1 in enumerate(entries9): 
    match_found = False 
    for counter2,entry2 in enumerate(entries10): 
     if match_found: 
      continue 
     if entry1[a]==entry2[a] and entry1[b]==entry2[b]: # the dictionaries only have some keys in common, but we care about a and b 
      match_found = True 
      joint_item = entry1 
      joint_items.append(joint_item) 
      #entries10.remove(entry2) # Tried this originally, but realised it messes with the original list object! 
    if match_found: 
     continue 
    else: 
     unmatched_items_9.append(entry1) 

성능은 실제로 일회성 스크립트이므로 문제가되지 않습니다.

+0

내부 루프의 'if match_found : break' (끝 부분)로'if match_found : continue '를 대체 할 수있을 것 같습니다. – SiggyF

+0

좋은 지적 @SiggyF! 예, 저는 할수 있습니다. – AP257

답변

8

당신이 현재하고있는 일에 해당하지만, 주변의 다른 방법은 다음과 같습니다

unmatched_items_10 = [d for d in entries10 if d not in entries9] 

를 코딩의 길보다 더 간결하지만,이 같은 성능 문제가 있습니다 : 그것은 시간이 걸릴 것입니다 각 목록의 항목 수에 비례합니다. 관심있는 길이가 약 9 또는 10 일 경우 (해당 숫자가 나타내는 것처럼 보임) 아무런 문제가 없습니다.

하지만 당신은 목록을 정렬하고 "단계별"에 의해 훨씬 더 나은 성능을 얻을 수있는 실질적인 길이의 목록에 대한

"병렬"( N이 긴 목록의 길이입니다 N log N에 비례 한 시간) 말하자면. 이 더 진보 된 접근법으로도 필요한 성능을 얻는 데 충분하지 않으면 다른 문제도 발생할 수 있습니다 (복잡성이 커지고 있음 ;-). 좋은 성능을 얻으 려하지 않는 한 매우 복잡한 것을 제안하지 마십시오 (이 경우 각 목록의 일반적인 길이를 으로 기재하십시오). 물론 "세부 사항"은 입니다.은 속도와 단순성간에 좋은 절충안 인 피킹 알고리즘에 대한 중요한 고려 사항입니다.

편집 : 영업 그는 두 dicts d1d2 한 두 목록에서 각각에 대해 관심이 무엇인지 보여주기 위해 자신의 질문을 편집하지 d1 == d2 여부 (무엇인지 in 운영자 검사), 오히려 d1[a]==d2[a] and d1[b]==d2[b]. 이 경우 in 운영자는 글쎄, 일부 펑키 포장하지 않고 있지만, 가장 ;-) 때 가능한 피할 것 합병증입니다 (사용할 수 없지만 all 내장이 솜씨를 대체

unmatched_items_10 = [d for d in entries10 
         if all(d[a]!=d1[a] or d[b]!=d2[b] for d2 in entries9)] 

난을 전환 한 논리 주위에 (!=or, 당 De Morgan's laws) 우리는 이 아닌이 일치하는 dicts를 원하기 때문입니다. 나는 문체 이유 if not anyif not all을 좋아하지 않아, 개인적으로

unmatched_items_10 = [d for d in entries10 
         if not any(d[a]==d1[a] and d[b]==d2[b] for d2 in entries9)] 

,하지만 any이기 때문에 수학은 위키피디아 페이지가 드 모건의 법률에 Extensions을 부르는하여 (완벽한 위치 : 그러나, 당신이 선호하는 존재 한정어 및 all 범용 수량 한정 기호, 말하자면 ;-). 성능은 거의 동일해야합니다 (그러나 OP는이 작업에서 성능이 그다지 중요하지 않다는 의견을 분명히했습니다).

+0

이 답변을 주셔서 감사합니다. 성능은 문제가 아닙니다. 일부 데이터를 정리하는 일회성 스크립트이고 소요 시간은 중요하지 않습니다. 불행히도 '항목이 없습니다'는 일치 조건이 더 복잡하기 때문에 작동하지 않습니다. 특정 필드를 비교해야합니다. 그것은 "d [a] == entries9_item [a] 및 d [b] == entries9_item [b]"와 더 비슷합니다. 나는 이것을 명확하게하기 위해 질문을 갱신 할 것이다. – AP257

+0

@ AP257, 그것은 처음에는 평등성 검사가 분명히 특별한 경우이며, 이것이 사용하고있는 것임을 언급하는 것이 좋았을 것입니다. 어쨌든 내 대답을 편집하여 코드가 어떻게 변하는 지 보여줍니다. –

+0

죄송합니다. 감사합니다. all()과 any()를 매우 깔끔하게 사용하십시오. joint_items리스트를 얻으려면, 내가 단순히 "joint_items = [d에 대해 d를 입력해야만한다고 생각하십니까?] 항목에서 d2에 대해 모두 (d [a] == d1 [a] 또는 d [b] == d2 [b])] "? 그건 반복적 인 것 같지만, 원래의 물건을 어지럽히는 것보다 아마 안전합니다. – AP257

0

Python stdlib에는 difflib.SequenceMatcher 클래스가 있습니다. difflib.SequenceMatcher는 원하는대로 사용할 수있는 것처럼 보이지만 사용 방법은 모르겠습니다.

0

intersection과 같은 sets 및 관련 방법을 사용하는 것이 좋습니다. 그러나 사전을 변경 불가능한 데이터로 변환하여 set (예 : string 초)에 저장할 수 있어야합니다. 이 작품이 좋아질까요?

a = set(str(x) for x in entries9) 
b = set(str(x) for x in entries10) 

# You'll have to change the above lines if you only care about _some_ of the keys 

joint_items = a.union(b) 
unmatched_items = a - b 

# Now you can turn them back into dicts: 
joint_items  = [eval(i) for i in joint_items] 
unmatched_items = [eval(i) for i in unmatched_items] 
+0

가능하면'dict.items'와'dict' 대신'str'과'eval'을 사용합니다. – SiggyF

관련 문제