2013-08-10 4 views
0

I는 다음과 같습니다 dicts의 목록을 가지고 :그룹화 데이터

[{TYPE, OBJECT_ID, ACTOR, EXTRA_FIELDS}, ...] 

나는 통과하고 {TYPE, OBJECT_ID}의 중복 집계 배우 a를하고 싶습니다 그래서 목록 :

시작으로 :

[ {'type': 'LOVE', 'obj_id': 1242, 'actor': 'bob', {..}}, 
     {'type': 'LOVE', 'obj_id': 1242, 'actor': 'dave', {..}}, 
     {'type': 'FAV', 'obj_id': 1242, 'actor': 'sam', {..}}, 
     {'type': 'LOVE', 'obj_id': 242, 'actor': 'bob', {..}}] 

끝을 위로 :

[ {'type': 'LOVE', 'obj_id': 1242, 'actor': ['bob', 'dave'], {..}}, 
     {'type': 'FAV', 'obj_id': 1242, 'actor': ['sam'], {...}}, 
     {'type': 'LOVE', 'obj_id': 242, 'actor': ['bob'], {...}} ] 
,

EXTRA_FIELDS는 병합 할 필요가 없으며 집계 된 항목 중 하나의 데이터 만 사용할 수 있습니다.

어떻게 이것을 파이썬으로 할 수 있습니까? 하나 - 라이너를 좋아하는 경우에 input이 튜플 (하지 세트), 무엇을,

TYPE= 0 
OBJECT_ID= 1 
ACTOR= 2 
EXTRA_INFO= 3 
keys= set([ (e[TYPE] , e[OBJECT_ID]) for e in input ]) 
output= { k: [ (e[ACTOR] , e[EXTRA_INFO]) for e in input if (e[TYPE] , e[OBJECT_ID]) == k ] for k in keys } 

에 대한 또는 목록이라고 가정

+4

그 객체 리터럴은하지 마십시오

나중에 컬렉션을 반복 할 거라면 당신이 바로 루프에서 튜플 (심지어 중첩 된 것들) 압축을 풀 수 있기 때문에,이 방법은 매우 쉽다 의미가 있습니다. 그들은 리터럴입니다. '{a, b}'는 (a와 b가 정의되었다고 가정하면)'set ([a, b])'를 제공 할 것이다. – FakeRainBrigand

+4

실제 데이터를 게시하십시오. –

+0

당신의 구문은 매우 생소합니다. 예를 들어 {TYPE, OBJECT_ID, ACTOR, EXTRA_FIELDS}는 무엇입니까? - 파이썬에서 그 세트는 그렇지만 당신이 그렇게 생각하지 않는다고 생각합니까? –

답변

0

내가 그것을 할 거라고 방법 :

def merge_dicts(list_of_dicts): 
    lookup = {} 
    results = [] 
    for d in list_of_dicts: 
     key = (d['type'], d['obj_id']) 
     try: # it's easier to ask forgiveness than permission 
      lookup[key]['actor'].append(d['actor']) 
     except KeyError: 
      val = {'type': d['type'], 
        'obj_id': d['obj_id'], 
        'actor': [d['actor']], # note, extra [] around value to make it a list 
        'extra_fields': d['extra_fields']} 
      lookup[key] = val 
      results.append(val) 

    return results 

결과 목록에 포함 된 사전에 키 값의 튜플에서 lookup DICT지도. 나중에 같은 키를 가진 다른 사전을 만나면 해당 출력 사전의 actor 값이 변경됩니다.

사전 목록 데이터 구조를 없애고 대신 type, obj_id 키를 actors, extra_fields 값으로 매핑하는 단일 사전으로 이동하는 것이 더 자연 스럽습니다. 당신이 이전 목록에서 항목을 병합 된 이후와, 순서의 일부 (단지 순서가 손실되었습니다 dicts의 목록이 한 데이터의 대부분이

def merge_dicts2(list_of_dicts): 
    results = {} 
    for d in list_of_dicts: 
     key = (d['type'], d['obj_id']) 
     try: 
      results[key][0].append(d['actor']) 
     except KeyError: 
      results[key] = ([d['actor']], d['extra_fields']) 

    return results 

했다있다 : 여기에 그 같을 것이다 무엇 상관없이 길을 잃을 것입니다.)

combined_dict = merge_dicts(list_of_dicts) 

for (type, obj_id), (actors, extra_fields) in combined_dict.items(): 
    # do stuff with type, obj_id, actors, extra_fields 
0

는 :

output= { k: [ (e[2] , e[3]) for e in input if (e[0] , e[1]) == k ] for k in [ (e[0] , e[1]) for e in input ] } 

가정 input 것을는 사전의 목록입니다 이는 다음과 같습니다.

keys= set([ (e['type'] , e['obj_id']) for e in input ]) 
output= { k: [ { 'actor':e['actor'] , 'extra_info':e['extra_info'] } for e in input if (e['type'] , e['obj_id']) == k ] for k in keys } 

또는

output= { k: [ { 'actor':e['actor'] , 'extra_info':e['extra_info'] } for e in input if (e['type'] , e['obj_id']) == k ] for k in [ (e['type'] , e['obj_id']) for e in input ] } 

물론 이러한 이해가 무엇인지 수동으로 작성할 수도 있지만 데이터 용량이 너무 크고 하위 수준 최적화가 필요한 성능 문제가 발생하기 전에는 권장하지 않습니다.

0

귀하의 목록 나는 alist으로 표시됩니다.

actors = {} 
extra = {} 
for x in alist: 
    if actors.has_key([(x['type'],x['obj_id'])): 
     actors[x['type'],x['obj_id']].append(x['actor']) 
    else: 
     actors[x['type'],x['obj_id']] = [] 
    extra[x['type'],x['obj_id']] = x['extra'] 

outlist = [] 
for k in actors.keys(): 
    x = {} 
    x['type'], x['obj_id'], x['actor'], x['extra'] = k[0], k[1], actors[k], extra[k] 
    outlist.append(x) 

outlist은 출력 목록입니다.

0

문제를 구성 요소로 분해해야합니다. 인덱스이 경우 반환, 그리고

for dict in list_of_dicts: 
    dict['actor'] = [dict['actor']] 

가 특정 쌍 dicts의 목록에 있는지 확인하는 방법을 쓸 필요

당신이해야 할 첫 번째 일은 목록에 모든 배우를 변경할 수 있습니다 입니다 :

def check_pair(list_of_dicts,type,obj_id): 
    #return index of matching pair, None otherwise 
    index = -1 
    for dict in list_of_dicts: 
    index += 1 
     if dict['type'] == type and dict['obj_id'] == obj_id: 
     return index 
    else: 
     return None 

는 그런 다음 새 목록에 추가 또는, obj_id 및 유형이 이미있는 경우, 추가하거나, (새로운 데이터를 저장하기 위해) 새로운 목록을 작성하고 기존 목록을 통해 갈 필요가 그 놈에게 배우.

new_list = [] 
for dict in list_of_dicts: 
    j = check_pair(new_list,dict['type'],dict['obj_id']) 
if j == None: 
    new_list.append(dict) 
else: 
    new_list[j]['actor'].append(dict['actor']) 

이 같은 dicts의 목록을 가진 것은 꽤 틀에 얽매이지 않는 물건이라고 지적한다, 당신은 정말 당신의 데이터 구조를 분별 할 수있는 방법을 파악해야한다.

-2

첫 번째 해결책은 식별자 집합 (형식과 obj_id의 고유 한 조합 집합)을 얻는 것입니다. 그런 다음 각 조합에 대한 액터 목록을 가져옵니다.것

actors_dict = {} 
for item in input_list: 
    actors_dict.setdefault((item['type'], item['obj_id']), []).append(item['actor']) 
output_list = [{'type': type, 'obj_id': obj_id, 'actor': actors} 
    for (type, obj_id), actors in actors_dict.iteritems()]  

또는 (예를 들어, 경우에 당신이 병합 다른 값을 추가)이 글을 쓰는 좀 더 유연한 방법 :

identifiers = set((item['type'], item['obj_id']) for item in input_list) 
output_list = [] 
for type, obj_id in identifiers: 
    output_list.append({ 
     'type': type, 
     'obj_id': obj_id, 
     'actor': [item['actor'] for item in input_list 
      if item['type'] is type and item['obj_id'] is obj_id] 
     }) 

또는 사전 키로 튜플을 활용

output_dict = {} 
for item in input_list: 
    k = item['type'], item['obj_id'] 
    if k in output_dict: 
     output_dict[k]['actor'].append(item['actor']) 
    else: 
     item['actor'] = [item['actor']] 
     output_dict[k] = item 
output_list = output_dict.values() 

(이 마지막 하나는 입력 목록을 변경 않습니다.)

여기