2016-05-09 3 views
3

Мой текущий список:список объединения словарей, которые имеют список инициализации

my_list = [ 
    {'id': 1, 'val': [6]}, 
    {'id': 2, 'val': [7]}, 
    {'id': 3, 'val': [8]}, 
    {'id': 2, 'val': [9]}, 
    {'id': 1, 'val': [10]}, 
] 

Желаемый результат:

my_list = [ 
    {'id': 1, 'val': [6, 10]}, 
    {'id': 2, 'val': [7, 9]}, 
    {'id': 3, 'val': [8]}, 
] 

, что я пытался до сих пор:

my_new_list = [] 
    id_set = set() 

    for d in my_list: 
     if d['id'] not in id_set: 
      id_set.add(d['id']) 
      temp = {'id': d['id'], 'val': d['val']} 
      my_new_list.append(temp) 
     else: 
      # loop over the new list and find the dict which already have d['id'] and update by appending value 
      # but this is not efficient 

любой другой более эффективный подход или может быть некоторая встроенная функция, о которой я не знаю.

PS: Заказ важен!

+0

Учитывая новый список будет иметь уникальное значение для 'id', вы можете использовать словарь вместо с' id' в качестве ключа. Таким образом, вам не нужно перебирать новый список, вы можете получить к нему доступ по идентификатору напрямую. – spectras

+0

Важен ли список выходных данных? – schwobaseggl

+0

@schwobaseggl: да, порядок важен, поэтому я не использовал словарь, как упомянуто y spectras – Wendy

ответ

4

.setdefault() ваш друг:

(. Мы должны использовать collections.OrderedDict запомнить порядок, что ключи были первым вставленный)

>>> import collections 

>>> result = collections.OrderedDict() 
>>> for d in my_list: 
...  result.setdefault(d["id"], []).extend(d["val"]) 

>>> lst = [] 
>>> for k, v in result.items(): 
...  lst.append({"id": k, "val": v}) 
+0

Форма понимания в виде второй части довольно читаема, а также 'lst = [{" id ": k," val ": v } для k, v в result.items()] ' – spectras

0

Вы можете использовать itertools.groupby для того, чтобы сортировать и группировать оригинал list на 'id' и скопируйте 'val' для каждой группы:

from itertools import groupby 

key_fnc = lambda d: d['id'] 
result = [ 
    {'id': k, 'val': sum([d['val'] for d in g], [])} 
     for k, g in groupby(sorted(my_list, key=key_fnc), key=key_fnc) 
] 
1

же подход, как ozgur, но с использованием collections.defaultdict:

>>> from collections import defaultdict 
>>> d = defaultdict(list) 
>>> for dd in my_list: 
     d[dd['id']].extend(dd['val']) 
>>> d 
defaultdict(<type 'list'>, {1: [6, 10], 2: [7, 9], 3: [8]}) 
>>> 
>>> lst = [] 
>>> for k,v in d.iteritems(): 
     lst.append({'id':k, 'val':v}) 

>>> lst 
[{'id': 1, 'val': [6, 10]}, {'id': 2, 'val': [7, 9]}, {'id': 3, 'val': [8]}] 
>>> 
+0

порядок важен для меня. мы можем сделать это, используя 'OrderedDict' вместо' defaultdict'. – Wendy

+0

Если вы заказываете оригинал 'my_list', он сохраняет порядок, так как он выполняет итерацию. –

Смежные вопросы