Supponendo che il numero di chiavi e valori per chiave, sono entrambi arbitraria e a priori sconosciuto, è più semplice ottenere il risultato con i cicli for, ovviamente:
Può essere compresso, ma sono dubbioso circa le implicazioni di prestazione di farlo (se le strutture di dati coinvolte sono così grandi da garantire l'ottimizzazione delle prestazioni, la costruzione di qualsiasi struttura ausiliaria aggiuntiva in memoria oltre ciò che è strettamente necessario potrebbe trasformarsi costoso - questo mio semplice approccio è particolarmente attento a evitare tali strutture intermedie).
: un'altra alternativa, particolarmente interessante se le strutture di dati complessive sono enormi ma in alcuni casi di utilizzo è possibile che siano necessari solo "frammenti" della struttura "trasformata", è di creare una classe che fornisce l'interfaccia hai bisogno, ma lo fa "al volo", piuttosto che in una trasformazione "big bang", "una volta per tutte" (questo potrebbe essere particolarmente utile se la struttura originale può cambiare e quella trasformata deve riflettere lo stato attuale dell'originale, ecc. ecc.).
Ovviamente, per tale scopo è molto utile identificare esattamente quali caratteristiche di un "elenco di dizionari" utilizzarebbe il codice downstream. Supponiamo ad esempio che tutto ciò di cui hai bisogno sia effettivamente indicizzazione di "sola lettura" (non cambiando, iterando, affettando, ordinando, ...): X[x]
deve restituire un dizionario in cui ogni chiave k si associa ad un valore tale (caling O
dizionario originale delle liste) X[x][k] is O[k][x]
. Poi:
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())
se non in realtà bisogno la struttura avvolta per monitorare le modifiche a quello originale, quindi __getitem__
potrebbe benissimo anche "cache" del dict è il ritorno:
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
Si noti che questo approccio può finire con qualche duplicazione nella cache, ad esempio, se gli elenchi di O
hanno ciascuno 7 elementi ciascuno, la cache a x==6
e x==-1
può finire con due dendici uguali; se questo è un problema, ad esempio, è possibile normalizzare i valori negativi s in __getitem__
aggiungendo len(self.O)
prima di procedere.
Se è necessaria anche l'iterazione, oltre a questa semplice indicizzazione, non è troppo difficile: basta aggiungere un metodo __iter__
, facilmente implementabile ad es. come un semplice generatore ...:
def __iter__(self, x):
for i in xrange(len(self.O)):
yield self[i]
E così via, in modo incrementale, se e come avete bisogno sempre di più le funzionalità di un elenco (nel peggiore dei casi, una volta che avete implementato questa __iter__
, si può costruire self.L = list(self)
- di ritornare al "big bang" approccio - e, per ogni ulteriore richiesta, punt a self.L
... ma dovrai fare uno speciale metaclass se vuoi adottare questo approccio anche per i metodi specialioppure utilizzare il trucco più sottile come self.__class__ = list; self[:] = self.L
seguito da appropriato del
s ;-).
Si consiglia di chiarire la tua domanda un po '... Mi c'è voluto del tempo per capire cosa si vuole dal vostro esempio: convertire una mappa con due tasti (key1 , key2) ciascuno con una lista di valori (della stessa lunghezza, ma variabile) per un elenco di coppie, e in coppia alla posizione i, key1 e key2 impostano l'elemento iith della rispettiva lista. È così? –
Perché il fascino di farlo senza cicli? Questo è un limite stupido. – jcdyer
non era un dovere, ho scritto "preferibilmente". Pensato ci potrebbe essere un rapido modo pitonico per farlo (alcune funzioni magiche di cui ancora non sapevo;)) –