Zakładając liczbę klawiszy, a wartości na klucz, są zarówno arbitralne i a priori nieznany, najprościej jest uzyskać wynik z pętlami, oczywiście:
itit = thedict.iteritems()
k, vs = next(itit)
result = [{k: v} for v in vs]
for k, vs in itit:
for d, v in itertools.izip(result, vs):
d[k] = v
Może być zwinięty, ale mam wątpliwości co do tego, jakie są tego konsekwencje (jeśli struktury danych są tak duże, że uzasadniają optymalizację wydajności, budowanie dodatkowej dodatkowej pamięci w pamięci poza to, co jest ściśle wymagane, może się okazać kosztowne - to moje proste podejście jest szczególnie ostrożne, aby uniknąć takich pośrednich struktur).
Edit: inna alternatywa, szczególnie interesujące, jeśli ogólne struktury danych są ogromne, ale w niektórych przypadkach zastosowania może trzeba tylko „kawałki” z „przekształconego” strukturze, jest budowanie klasy, która udostępnia interfejs czego potrzebujesz, ale robi to "w locie", a nie w "wielkim wybuchu", "raz na zawsze" (może to być szczególnie pomocne, jeśli oryginalna struktura może się zmienić, a przekształcona musi odzwierciedlać obecny stan oryginału, itp. itp.).
Oczywiście, w tym celu bardzo pomocne jest dokładne określenie, jakie cechy "listy słowników" będzie wykorzystywać twój kod źródłowy. Załóżmy na przykład, że wszystko, czego potrzebujesz, to indeksowanie "tylko do odczytu" (niezmiennianie, iterowanie, dzielenie, sortowanie, ...): X[x]
musi zwracać słownik, w którym każdy klawisz k mapuje wartość, która (kalingowanie O
oryginalny słownik list) X[x][k] is O[k][x]
. Następnie:
class Wrap1(object):
def __init__(self, O):
self.O = O
def __getitem__(self, x):
return dict((k, vs[x]) for k, vs in self.O.iteritems())
Jeśli nie w rzeczywistości potrzebują owinięte strukturę do śledzenia zmian do pierwotnego, a następnie __getitem__
może dobrze także „cache” dict to powrót:
class Wrap2(object):
def __init__(self, O):
self.O = O
self.cache = {}
def __getitem__(self, x):
r = self.cache.get(x)
if r is None:
r = self.cache[x] = dict((k, vs[x]) for k, vs in self.O.iteritems())
return r
Należy pamiętać, że takie podejście może zakończyć się pewnym duplikowaniem w pamięci podręcznej, np. jeśli listy O
mają po 7 pozycji, pamięć podręczna pod numerami x==6
i x==-1
może zakończyć się dwoma równorzędnymi dyktami; jeśli to jest problem, możesz na przykład normalizować negatywne x
s w __getitem__
, dodając do nich len(self.O)
, zanim przejdziesz dalej.
Jeśli potrzebujesz również iteracji, a także tego prostego indeksowania, to nie jest zbyt trudne: wystarczy dodać metodę __iter__
, łatwo zaimplementowaną np. jako prosty generator ...:
def __iter__(self, x):
for i in xrange(len(self.O)):
yield self[i]
I tak dalej, stopniowo, jeśli i tak trzeba coraz więcej funkcjonalności listę za (w najgorszym przypadku, gdy wdrożyły ten __iter__
, można zbudować self.L = list(self)
- powrót do „wielkiego wybuchu” podejście - i, dla każdego kolejnego żądania, punt do self.L
... ale będziesz musiał zrobić specjalną metaclass, jeśli chcesz wziąć to podejście również dla metod specjalnych lub użyć jakiejś subtelniejszej sztuczki, takiej jak self.__class__ = list; self[:] = self.L
przez odpowiednie del
s ;-).
Możesz wyjaśnić swoje pytanie trochę ... Zajęło mi trochę czasu, aby zrozumieć, co chcesz ze swoim przykładzie: przekonwertować mapę z dwoma kluczami (klucz1 , key2) każdy z listą wartości (tej samej, ale różnej długości) do listy par, a para w pozycji i, klawisz1 i klucz2 jest ustawiony na ith element ich odpowiedniej listy. Czy to to? –
Dlaczego fascynacja robieniem tego bez pętli? To głupie ograniczenie. – jcdyer
to nie było konieczne, napisałem "najlepiej". Myślałem, że może to być szybki pythonic sposób to zrobić (niektóre funkcje magii jeszcze nie wiedziałem;)) –