2011-12-17 9 views
14

Come si seleziona una chiave hash casuale? Per my Flash+Perl card game Sto cercando di scegliere una carta a caso da un hash in cui le chiavi sono: "6 picche", "6" club, ecc in questo modo:Selezione di una chiave casuale da un hash

my $card; 
my $i = 0; 
for $card (keys %{$user->{HAND}}) { 
    last if rand(++$i) < 1; 
} 
delete $user->{HAND}->{$card}; 
print "random card: $card\n"; 

Mi chiedo se è il modo corretto o se ci è un modo migliore.

+1

non corretta a tutti. La '$ card' nel ciclo' for' è ["implicitamente locale al ciclo e recupera il suo valore precedente all'uscita dal ciclo"] (http://search.cpan.org/perldoc?perlsyn#Foreach_Loops). Cioè, la '$ card' nella tua dichiarazione di stampa è una variabile diversa da' $ card' nel ciclo 'for'. – mob

+0

Inoltre, il fatto che si generi un nuovo numero ogni passaggio altera il risultato. – ikegami

risposta

16

Un po 'più conciso:

my $random_value = $hash{(keys %hash)[rand keys %hash]}; 
+1

mi hai ispirato, controlla '$ random_val_3' nel mio post. –

+0

nice refp! l'arte della confusione perl !! – ennuikiller

+0

Grazie, cercavo il mio $ random_key = (keys% hash) [rand keys% hash]; –

14

Ottenere valore casuale da% hash


  1. Conservare le chiavi del tuo %hash in @hash_keys.
  2. generare un numero casuale compreso tra 0 e la lunghezza del @hash_keys
  3. ottenere la voce casuale @hash_keys
  4. utilizzare il tasto acquisita per ottenere il vostro valore casuale da %hash

frammento di esempio :

my %hash = ( 
    'stack' => 'overflow', 
    'face' => 'book', 
    'inter' => 'net' 
); 

## ALTERNATIVE 1 ## 
my @hash_keys = keys %hash; 

my $random_key = $hash_keys[rand @hash_keys]; 
my $random_value = $hash{$random_key}; 

## ALTERNATIVE 2 ## 
my $random_val_2 = (%hash)[1+2*int rand keys%hash]; # TIMTOWTDI 

## ALTERNATIVE 3 ## 
my $random_val_3 = [@_=%hash]->[1|[email protected]_];   # TIMTOWTDI 
+0

Che cosa significa "1 |" nell'ultima riga? –

+0

@AlexanderFarber è un OR bit a bit, assicurandosi di ottenere solo numeri dispari all'interno delle parentesi. '1 | 2 => 3', '1 | 0 => 1', '1 | 1 => 1'. Imposterà sempre il bit meno significativo in un numero intero a 1. –

+0

@refp: Trovo che questo restituisca sempre lo stesso valore la prima volta che viene chiamato: 'perl -Mstrict -wE 'il mio% hash = mappa {$ _ => $ _} 1..100; dì ((@ _ =% hash) [1 | rand @ _]) per 1..10; '' – Zaid

1

Ecco un altro modo (dimostrando come scegliere un elemento casuale da un elenco di lunghezza sconosciuta):

my $cards; 
my $chosen; 
while (my $card = each %{$user->{HAND}}) { 
    $chosen = $card if rand(++$cards) < 1; 
} 
+0

Oh ora capisco: non dovrei avere "ultimo" nel mio codice originale –

+0

Destra, $ scelto deve essere resettato più di una volta. – ysth

Problemi correlati