2011-04-14 3 views
3

나는 다음과 같은 규칙에 따라, dicts의 목록을 정리할 :삭제 dicts - 파이썬

1) dicts의 목록이 이미 정렬되어 있으므로 이전 dicts가 선호됩니다.
2) 하위 명령에서 ['name']['code'] 문자열 값이 목록의 상위에있는 동일한 상위 키 값과 일치하고 두 dict 사이의 의 차이 절대 값이 < 2 인 경우; 해당 사전은 이전 dict의 복제본으로 간주되며 목록에서 삭제됩니다.

{ 
'name':"ItemName", 
'code':"AAHFGW4S", 
'from':"NDLS", 
'to':"BCT", 
'cost':str(29.95) 
} 

이 같은 중복을 제거하는 가장 좋은 방법은 무엇입니까 : 여기

은 dicts의 목록에서 하나 딕셔너리입니까?

for i, d in enumerate(dictList): 
    # iterate through the list of dicts, starting with the first 
    for k,v in d.iteritems(): 
     # for each key-value pair in this dict... 
     for d2 in dictList[i:]: 
      # check against all of the other dicts "beneath" it 
      # eg, 
      # if d['name'] == d2['name'] and d['code'] == d2['code']: 
      #  --check the cost stuff here-- 

답변

3

이 일을 더 파이썬 방법이있을 수 있지만, 이것은 기본적인 의사입니다 :

+0

더 나은 기술적 방법 (특히 큰 목록에서 메모리 사용량을 줄이기 위해'yield '를 사용하는 Jochen의 대답)이 있지만, 나는 당신의 방법을 더 잘 읽을 수있다. – Pranab

0

뒤얽힌 문제의 종류하지만이 같은 작업 것이라고 생각하기 때문에

def is_duplicate(a,b): 
    if a['name'] == b['name'] and a['cost'] == b['cost'] and abs(int(a['cost']-b['cost'])) < 2: 
    return True 
    return False 

newlist = [] 
for a in oldlist: 
    isdupe = False 
    for b in newlist: 
    if is_duplicate(a,b): 
     isdupe = True 
     break 
    if not isdupe: 
    newlist.append(a) 
+0

감사합니다. Daniel. 예,리스트를 잘라내는 것이 나의 첫 번째 본능적 아이디어 였지만 1 년 후 코드를 다시 방문 할 때 두리스트를 사용하는 Yasser의 아이디어가 더욱 분명 해졌다고 생각합니다. 어떻게 생각해? – Pranab

3

당신은 그 비용이 당신이 사용할 수있는 정수라고 말합니다 :

def neardup(items): 
    forbidden = set() 
    for elem in items: 
     key = elem['name'], elem['code'], int(elem['cost']) 
     if key not in forbidden: 
      yield elem 
      for diff in (-1,0,1): # add all keys invalidated by this 
       key = elem['name'], elem['code'], int(elem['cost'])-diff 
       forbidden.add(key) 

다음은 덜 까다로운 방법입니다. 차이를 계산합니다 :

from collections import defaultdict 
def neardup2(items): 
    # this is a mapping `(name, code) -> [cost1, cost2, ... ]` 
    forbidden = defaultdict(list) 
    for elem in items: 
     key = elem['name'], elem['code'] 
     curcost = float(elem['cost']) 
     # a item is new if we never saw the key before 
     if (key not in forbidden or 
       # or if all the known costs differ by more than 2 
       all(abs(cost-curcost) >= 2 for cost in forbidden[key])): 
      yield elem 
      forbidden[key].append(curcost) 

두 가지 해결책을 사용하면 모든 항목에 대해 전체 목록을 다시 검색하지 않아도됩니다. 결국, (name, code)이 동등한 경우에만 비용이 발생하므로 사전을 사용하여 모든 후보를 빠르게 찾을 수 있습니다.

+0

'yield'와'set()'을 소개해 주셔서 감사합니다. 당신의 대답은 항상 기술적으로 굉장합니다! – Pranab