[PIPython] confronto tra dizionari

Alex Martelli aleaxit
Ven 19 Nov 2004 15:16:43 CET


On Monday 15 March 2004 10:14 pm, Simone Piunno wrote:
> On Monday 15 March 2004 18:20, ciccio a unical.it wrote:
> > Ho uno script che legge files in input, tutti dello stesso formato, solo
> > che ciascuno contiene dei valori numerici differenti.
> > Dopo la lettura dei files, per ognuno di essi ottengo un dizionario del
> > tipo:
> >
> > {('4', '8'): '0.1', ('3', '7'): '0.1', ('2', '6'): '0.1', ('1', '5'):
> > '0.1'} {('4', '8'): '0.2', ('3', '9'): '0.2', ('2', '6'): '0.2', ('1',
> > '5'): '0.2'}
> >
> > Cio' che vorrei fare, e non so se possibile, e' raggruppare le
> > informazioni in un unico dizionario del tipo:
> >
> > {('4','8'):['0.1','0.2'], ('3', '7'):['0.1', '-'], ('3',
> > '9'):['-','0.2'], ('2', '6'):['0.1','0.2'], ('1', '5'):['0.1','0.2']}
>
> Inefficiente (neanche tanto) ma sintetico:
>
> unico = {}
> for k in [x for d in dizionari for x in d.keys()]:
>     unico[k] = [d.get(k, '-') for d in dizionari]
>
> dove "dizionari" è una sequence dei tuoi dizionari di partenza.

Ragionevole, in effetti un po' inefficiente perche` per ogni chiave k che 
appaia N volte il body e` eseguito ripetutamente N volte (un'altra piccola 
inefficienza facilmente evitabile e` la "for x in d.keys()" dove "for x in d" 
fa lo stesso lavoro a minor prezzo:-).  Se si puo` "spendere" una riga in +:

import sets
risultato = {}
for k in sets.Set([x for d in dizionari for x in d]):
     risultato[k] = [d.get(k, '-') for d in dizionari]

sets.Set accetta come argomento un'arbitraria sequenza, anche con ripetizioni, 
di oggetti hashabili (quindi le chiavi di dizionari vanno sicuramente bene:-) 
e torna un oggetto "insieme", naturalmente senza ripetizioni, su cui si puo` 
iterare.  Ma la "import sets" e` indispensabile per usarlo, naturalmente.

Per recuperare parte della concisione, se questa e` ad esempio una funzione 
che dovrebbe finire con "return risultato", si puo` facilmente costruire il 
risultato al volo...:

import sets

def fondi(*dizionari):
  return dict([ (k, [d.get(k, '-') for d in dizionari]) 
            for k in sets.Set([x for d in dizionari for x in d]) ])

Qui il lavoro e` fatto tutto sulla singola istruzione return, anche se, 
naturalmente, gli effetti sulla chiarezza di questa estrema concisione sono 
decisamente discutibili.  Varie soluzioni intermedie tipo:

  chiavi = sets.Set([x for d in dizionari for x in d])
  return dict([ (k, [d.get(k, '-') for d in dizionari]) for k in chiavi ])

possono forse offrire il compromesso migliore fra chiarezza e concisione.


Alex




More information about the Python mailing list