2016-12-05 1 views
1

중복 값을 사전에 인식하고 그룹화하고 싶습니다. 이 question를 참조 구체적인 사용 사례를 들어사전에서 혼합 유형 값에 대한 중복 찾기

from pickle import dumps 
taxonomy = {} 
binder = defaultdict(list) 
for key, value in ds.items(): 
    signature = dumps(value) 
    taxonomy[signature] = value 
    binder[signature].append(key) 

: 나는 의사 해시를 구축 이렇게하려면 다음과 같이 설정 내 데이터의 (더 나은 서명을 읽기).

>>> ds['key1'] == ds['key2'] 
True 

이 하나가 항상 True 더 이상되지 않습니다 : :

>>> dumps(ds['key1']) == dumps(ds['key2']) 
False 

내가 덤프 출력의 키 순서가 모두 DICT 다릅니다 알

불행히도 나는 다음과 같은 문이 True 경우 실현 . / 붙여 넣기하면 ds['key1']ds['key2']의 출력이 새 사전에 붙여져 비교가 성공할 수 있습니다.

잔인한 대안으로 내 데이터 집합을 반복적으로 통과 수 및 OrderedDictdict 인스턴스를 대체 : 나는 모든 가능한 상황을 다루 여부를 알 수 없기 때문에

import copy 
def faithfulrepr(od): 
    od = od.deepcopy(od) 
    if isinstance(od, collections.Mapping): 
     res = collections.OrderedDict() 
     for k, v in sorted(od.items()): 
      res[k] = faithfulrepr(v) 
     return repr(res) 
    if isinstance(od, list): 
     for i, v in enumerate(od): 
      od[i] = faithfulrepr(v) 
     return repr(od) 
    return repr(od) 

>>> faithfulrepr(ds['key1']) == faithfulrepr(ds['key2']) 
True 

내가이 본래의 접근법은 걱정입니다.

어떤 다른 (일반) 대안을 사용할 수 있습니까?

def faithfulrepr(ds): 
    if isinstance(ds, collections.Mapping): 
     res = collections.OrderedDict(
      (k, faithfulrepr(v)) for k, v in sorted(ds.items()) 
     ) 
    elif isinstance(ds, list): 
     res = [faithfulrepr(v) for v in ds] 
    else: 
     res = ds 
    return repr(res) 

그러나 sortedrepr 자신의 단점이 있습니다 :

+0

그래서 같은 일 각'dict'의'repr'을 원하는 ... 어떤 이유로 당신에게 그 (것)들을 다만'적재하고 비교할 수 없는가? –

+0

음,'repr'은'pickle'을 사용하는 것보다 훨씬 쉽습니다. 불행히도'repr' 객체는 항상 두 인스턴스의 내용을 비교할만큼 충분하지 않습니다. 그것은'repr (ds [ 'key1']) == repr (ds [ 'key2'])'도'False'를 반환한다고 말했습니다 ... – nowox

+0

제가 의도 한 바는 - dict' 객체의 표현 *을 원합니다. 평등을 비교하십시오 - JSON/pickled /'str''d /'repr''d 등 ... 그냥 역순으로 비교하고 다시 비교해 보는 것이 어떻습니까? 예 :'loads (덤프 (ds [ 'key1'])) ==로드 (덤프 (ds [ 'key2']))'? –

답변

1

우선 여기 병목 인 deepcopy에 전화를 제거하는 것입니다

  1. 당신이 속에서의 싸움은 정말 사용자 정의 유형을 비교할 수 있습니다;
  2. 다른 유형의 키와 함께 매핑을 사용할 수 없습니다.

그래서 두 번째 것은 __eq__와 객체를 faithfulrepr 제거하고 비교 얻을 수 있습니다 :

binder, values = [], [] 
for key, value in ds.items(): 
    try: 
     index = values.index(value) 
    except ValueError: 
     values.append(value) 
     binder.append([key]) 
    else: 
     binder[index].append(key) 
grouped = dict(zip(map(tuple, binder), values))