2013-08-01 2 views
1

У меня есть питон словарь формы:Преобразовать список в словарь в Python

a1 = { 
     'SFP_1': ['cat', '3'], 
     'SFP_0': ['cat', '5', 'bat', '1'] 
    } 

Конечный результат мне нужен словарь, формы:

{'bat': '1', 'cat': '8'} 

В настоящее время я делаю это:

b1 = list(itertools.chain(*a1.values())) 
c1 = dict(itertools.izip_longest(*[iter(b1)] * 2, fillvalue="")) 

, который дает мне выход:

>>> c1 
{'bat': '1', 'cat': '5'} 

Я могу перебирать словарь и получать его, но может ли кто-нибудь дать мне более питонический способ сделать то же самое?

+1

Я думал, что ты хотел «8» на выходе, а не " 5' . (И вы действительно хотите, чтобы это была строка, если вы добавляете номера вверх? Почему бы не int?) –

ответ

6

Использование defaultdict:

import itertools 
from collections import defaultdict 

a1 = {u'SFP_1': [u'cat', u'3'], u'SFP_0': [u'cat', u'5', u'bat', u'1']} 

b1 = itertools.chain.from_iterable(a1.itervalues()) 
c1 = defaultdict(int) 
for animal, count in itertools.izip(*[iter(b1)] * 2): 
    c1[animal] += int(count) 
# c1 => defaultdict(<type 'int'>, {u'bat': 1, u'cat': 8}) 

c1 = {animal: str(count) for animal, count in c1.iteritems()} 
# c1 => {u'bat': '1', u'cat': '8'} 
+1

Kudos для 'chain'. Хотел бы я подумать об этом – inspectorG4dget

+0

Чистый! Спасибо :) – cisnik

2
In [8]: a1 = {        
     'SFP_1': ['cat', '3'], 
     'SFP_0': ['cat', '5', 'bat', '1'] 
    } 

In [9]: answer = collections.defaultdict(int) 

In [10]: for L in a1.values():     
    for k,v in itertools.izip(itertools.islice(L, 0, len(L), 2), 
           itertools.islice(L, 1, len(L), 2)): 
     answer[k] += int(v) 

In [11]: answer 
Out[11]: defaultdict(<type 'int'>, {'bat': 1, 'cat': 8}) 

In [12]: dict(answer) 
Out[12]: {'bat': 1, 'cat': 8} 
0

Попробуйте collections.defaultdict(int): Из инструкции -

>>> s = 'mississippi' 
>>> d = defaultdict(int) 
>>> for k in s: 
...  d[k] += 1 
... 
>>> d.items() 
[('i', 4), ('p', 2), ('s', 4), ('m', 1)] 

Это должно позволить вам попасть туда, куда вам нужно.

0

Что бы ни стоило чистое решение Python, вот одно.

a1 = {'SFP_1': ['cat', '3'], 'SFP_0': ['cat', '5', 'bat', '1']} 

def count(what): 
    sums = {} 
    for items in what.itervalues(): 
     for k, v in zip(items[::2], items[1::2]): 
      if k in sums: 
       sums[k] = str(int(sums[k]) + int(v)) 
      else: 
       sums[k] = v 

    return sums 

count(a1) дает, {'bat': '1', 'cat': '8'}.

+0

'dict_obj.has_key (key)' устарел. Вместо этого используйте 'key в dict_obj'. – falsetru

+0

Просто заметьте, код немного проще, если вам не нужны, чтобы они оказались в виде строк. Первая строка после 'if' будет' sums [k] + = int (v) ', а вторая следующая строка:' sums [k] = int (v) '. – FakeRainBrigand

+0

@falsetru, спасибо. Я перепутался с другим языком и попробовал 'sums has k' (что очень не понравилось). – FakeRainBrigand

0

Вы можете использовать collections.Counter класс, который является в основном специализированной версией collections.defaultdict (INT) с хорошими дополнительными методами и красивым названием:

from collections import Counter 


def count(dct): 
    # Counter is specialized version of defaultdict(int) 
    counter = Counter() 
    for values in dct.viewvalues(): 
     assert len(values) % 2 == 0, "{!r} must have even length".format(values) 
     # iterate by pairs 
     for i in xrange(0, len(values) - 1, 2): 
      counter[values[i]] += int(values[i + 1]) 
    # convert frequencies to strings 
    return {word: str(freq) for word, freq in counter.viewitems()} 


if __name__ == "__main__": 
    a1 = {"SFP_1": ["cat", "3"], 
      "SFP_0": ["cat", "5", "bat", "1"] 
      } 
    print count(a1)