2012-02-13 7 views
7

Qual è il modo più elegante per trasformare un hash dentro e fuori?Whay è il modo più elegante per trasformare un hash dentro e fuori?

Con questo intendo sostituire chiavi con valori e viceversa (presupponendo che tutti i valori siano al 100% univoci).

E.g.

Inizia con

my %start = (1=>"a", 2=>"b", 3=>"c"); 

# ... 

# PROFIT: 
my %finish = ("c" => 3, "b" => 2, "a" => 1); 

so che posso farlo nel modo forza bruta:

foreach my $key (keys %start) { 
    my $value = $start{$key}; 
    $finish{ $value } = $key; 
} 

Ma questo non può essere il modo più Perly-elegante di farlo!

+0

tuo il metodo della forza bruta non funziona correttamente. Dovresti eseguire il ciclo su 'keys% start'. – cjm

+2

Che cosa significa "100% univoco"? Lavori nella pubblicità? Qualcosa può essere "unico al 95%"? Dici a tua moglie che lei è il tuo "amore unico al 95%"? –

+0

@cjm - proprio come sei. Ho modificato per correggere il codice, e ho aggiunto un po 'di pulizia dichiarando che le variabili sono lessicali nel più piccolo ambito (in altre parole, ho aggiunto 'my' ovunque). Ike - sentiti libero di ripristinare le modifiche se non sei d'accordo. – DVK

risposta

15

reverse è probabilmente tra i modi più idiomatiche:

my %finish = reverse %start; 

Questo funziona, perché contrario prende il %start hash come una lista della forma (key1 valore1 valore2 chiave2 ... Keyn valoreN); quindi inverte inverte l'elenco (valoreN chiaveN ... valore1 chiave1). Assegnazione di tale elenco a una variabile hash poi lo trasforma in un hash con elementi dispari diventare chiavi e anche elementi che diventano valori

oppure è possibile utilizzare map (meno elegante ma ancora idiomatica):

my %finish = map { ($start{$_} => $_) } keys %start; 
+3

'@finish {value% start} = keys% start' conserva le coppie esistenti. – tchrist

+1

'reverse% start' è intelligente, ma forse un po 'troppo intelligente. – cjm

+0

@tchrist - potresti chiarire per favore? Cosa significa "preserva le coppie esistenti"? – Ike

10
my %start = (1=>"a", 2=>"b", 3=>"c"); 

my %finish; 
@finish{values %start} = keys %start; 
+0

La settimana scorsa mi ci sono voluti mezzo ora [CENSURATA] per spiegare quella soluzione ad una classe Perl principiante. Ho deciso di rimuoverlo dai materiali. Semplicemente * non possono * capire le fette di hash. Si bloccano nella testa che "@" significa matrice; non capiscono che ci vuole il '{' per significare un hash e che il '@' è immateriale. – tchrist

+1

Virtuale +1 (non può ancora sopravvivere) per una soluzione intelligente. Non sono un principiante assoluto quindi non ho avuto lo stesso problema degli studenti nel commento sopra :) – Ike

+0

@ike - dovresti avere un rappresentante sufficiente per votare in modo non virtualmente ora. E +1 da parte mia per una grande espressione idiomatica – DVK

Problemi correlati