2012-01-19 13 views
6

Mam jakąś gadatliwą logikę, którą chciałbym skompaktować z pewnymi pojęciami.Scalona lista i zrozumienie dyktafonu

Zasadniczo mam obiekt dict, z którego czytam, z którego mam 16 wartości, które mnie interesują. Dostaję klucze, które chcę z poniższej zrozumieniem:

["I%d" % (i,) for i in range(16)] 

Słownik źródło rodzaj wygląda następująco:

{ "I0": [0,1,5,2], "I1": [1,3,5,2], "I2": [5,9,10,1], ... } 

Chciałbym zasadniczo map tego słownika być coś to:

[ 
    { "I0": 0, "I1": 1, "I2": 5, ... } 
    { "I0": 1, "I1": 3, "I2": 9, ... } 
    ... 
] 

Jak mogę map rzeczy z listy i słownik listowe do przekształcenia moje źródło dict do mojej listy odbiorców słowników?

Odpowiedz

7

Jest to w pełni funkcjonalne rozwiązanie, które można zastosować w dowolnym rozmiarze.

d = { "I0": [0,1,5,2], "I1": [1,3,5,2], "I2": [5,9,10,1]} 
map(dict, zip(*map(lambda (k, v): map(lambda vv: (k, vv), v), d.iteritems()))) 

opracowanie: (używam ipython i podkreślenia _ oznacza poprzednią wyjście)

In [1]: d = {'I0': [0, 1, 5, 2], 'I1': [1, 3, 5, 2], 'I2': [5, 9, 10, 1]} 

In [2]: map(lambda (k, v): map(lambda vv: (k, vv), v), _.iteritems()) 
Out[2]: 
[[('I1', 1), ('I1', 3), ('I1', 5), ('I1', 2)], 
[('I0', 0), ('I0', 1), ('I0', 5), ('I0', 2)], 
[('I2', 5), ('I2', 9), ('I2', 10), ('I2', 1)]] 

In [3]: zip(*_) 
Out[3]: 
[(('I1', 1), ('I0', 0), ('I2', 5)), 
(('I1', 3), ('I0', 1), ('I2', 9)), 
(('I1', 5), ('I0', 5), ('I2', 10)), 
(('I1', 2), ('I0', 2), ('I2', 1))] 

In [4]: map(dict, _) 
Out[4]: 
[{'I0': 0, 'I1': 1, 'I2': 5}, 
{'I0': 1, 'I1': 3, 'I2': 9}, 
{'I0': 5, 'I1': 5, 'I2': 10}, 
{'I0': 2, 'I1': 2, 'I2': 1}] 
6

Jak bym go rozwiązać:

Po pierwsze, chciałbym uzyskać dla każdego klawisza listę zawierającą krotki, gdzie pierwszym elementem byłby klucz, a drugi byłby jedną z wartości z listy:

>>> [ [ (k, i) for i in l] for k, l in d.items() ] 
[[('I1', 1), ('I1', 3), ('I1', 5), ('I1', 2)], 
    [('I0', 0), ('I0', 1), ('I0', 5), ('I0', 2)], 
    [('I2', 5), ('I2', 9), ('I2', 10), ('I2', 1)]] 

Wtedy że poprzecznie do tej listy, tworząc listę krotki zawierających każdy odpowiedni klucz, za pomocą funkcji pocztowy:

>>> list(zip(*[ [ (k, i) for i in l] for k, l in d.items() ])) 
[(('I1', 1), ('I0', 0), ('I2', 5)), 
(('I1', 3), ('I0', 1), ('I2', 9)), 
(('I1', 5), ('I0', 5), ('I2', 10)), 
    (('I1', 2), ('I0', 2), ('I2', 1))] 

tych listach podrzędnych może przekazywany jako parametr do konstruktora dict:

>>> [dict(lp) for lp in zip(*[ [ (k, i) for i in l] for k, l in d.items() ])] 
[{'I0': 0, 'I1': 1, 'I2': 5}, 
{'I0': 1, 'I1': 3, 'I2': 9}, 
{'I0': 5, 'I1': 5, 'I2': 10}, 
{'I0': 2, 'I1': 2, 'I2': 1}] 

W praktyce jednak nigdy nie poleciłbym, aby robił coś takiego w jednej linii:

>>> pairs = [ [ (k, i) for i in l] for k, l in d.items() ] 
>>> transversed = zip(*pairs) 
>>> ds = [dict(t) for t in transversed] 
>>> pprint(ds) 
[{'I0': 0, 'I1': 1, 'I2': 5}, 
{'I0': 1, 'I1': 3, 'I2': 9}, 
{'I0': 5, 'I1': 5, 'I2': 10}, 
{'I0': 2, 'I1': 2, 'I2': 1}] 

Właściwie to ja Wydaje mi się, że wysłałem tę odpowiedź głównie, aby zaproponować podział rozwiązania na więcej niż jedną linię.

+0

+1 do opracowania krok po kroku. Nasze podejścia są takie same, z wyjątkiem tego, że szeroko wykorzystałem 'map' :) – qiao

+0

@qiao tak, przyjęliśmy to samo podejście w bardziej abstrakcyjny sposób. Po prostu mam pewne preferencje co do rozumienia listy, ale twoje rozwiązanie jest doskonałe. – brandizzi

0

Jest krótkie i proste rozwiązanie:

keys = data.keys() 
values = data.values() 
transformed = [dict(zip(keys, t)) for t in zip(*values)] 

Kluczem tutaj jest transpozycji wartości macierzy, która jest wykonana z zip(*values), a potem po prostu odtworzyć dicts.