2016-03-10 2 views
0

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

Вот что происходит:

>>> vals 
[(5, u'3'), (5, u'3'), (8, u'1'), (8, u'1')] 
>>> dict(vals) 
{8: u'1', 5: u'3'} 

Вот что я хочу, чтобы это произошло

>>> vals 
[(5, u'3'), (5, u'3'), (8, u'1'), (8, u'1')] 
>>> foo(vals) 
{8: [u'1',u'1'], 5: [u'3',u'3']} 

Есть некоторые другие функции питона (foo в предыдущем случае), что делает это?

ответ

4

Это легко сделать с помощью setdefault:

def foo(some_list): 
    result = {} 
    for k, v in some_list: 
     result.setdefault(k, []).append(v) 

    return result  

(Использование setdefault является более эффективным, чем использование get(k, []) + [v], как мы делаем Append на месте)

+0

Должен признаться, что это лучше, чем мой ответ длинным выстрелом. +1 – zondo

1

Вы можете сделать это:

def foo(vals): 
    x = {} 
    for k, v in vals: 
     x[k] = x.get(k, []) + [v] 
    return x 

Я использую x.get(k, []) так, что если k уже в x, мы добавим ставить v в конце, но если это не так, мы будем ставить v на конец [] и использовать его для x[k]. Более длинный, но более быстрый способ - сначала проверить, есть ли, и если это так, добавьте его. Это быстрее, потому что мы не создаем новый список каждый раз, когда:

def foo(vals): 
    x = {} 
    for k, v in vals: 
     if k in x: 
      x[k].append(v) 
     else: 
      x[k] = [v] 

Вы также можете сделать это с try-except блока:

def foo(vals): 
    x = {} 
    for k, v in vals: 
     try: 
      x[k].append(v) 
     except KeyError: 
      x[k] = [v] 
+0

Этот подход очень неэффективен i f вы обрабатываете большие списки, так как на каждой итерации вы создаете новый список для ключа, копируя старый. – donkopotamus

+0

@ donkopotamus: Хорошо; Я редактировал. Как это? – zondo

+0

Гораздо лучше :-). Причина «setdefault» по-прежнему лучше для такого рода задач (в отличие от вашей улучшенной версии) заключается в том, что поиск ключей должен происходить только один раз. – donkopotamus

1

Значения dict должны быть списки, которые вы выделять, когда ключ не существует, и который вы добавляете, если ключ уже существует.

def foo(some_list): 
    result = {} 
    for k,v in some_list: 
    if k in result: 
     result[k].append(v) 
    else: 
     result[k] = [ v ] 
    return result  
2

Я предлагаю популярные коллекции модулей и defaultdict в этом вопросе.

from collections import defaultdict 
vals = [(5, u'3'), (5, u'3'), (8, u'1'), (8, u'1')] 
def foo(lst): 
    d = defaultdict(list) 
    for key, value in lst: 
     d[key].append(value) 
    return d 
print foo(vals) 
# defaultdict(<type 'list'>, {8: [u'1', u'1'], 5: [u'3', u'3']}) 
1

Вы можете также использовать defaultdict:

from collections import defaultdict 

vals = [(5, u'3'), (5, u'3'), (8, u'1'), (8, u'1')] 

d = defaultdict(list) 
for key, value in vals: 
    d[key].append(value) 
Смежные вопросы