2011-07-13 12 views
5

Mam mieszania identyfikatorów ciągów. Jaki jest najlepszy sposób przetasowania identyfikatorów?Jak przetasować wartości w haszdzie?

Jako przykład, mój hash przypisuje następujące identyfikatory:

this => 0 
is => 1 
a => 2 
test => 3 

Teraz chciałbym losowo przetasować to. Przykładowy wynik byłby:

this => 1 
is => 0 
a => 3 
test => 2 
+0

Można zawsze stworzyć mieszania różnych skrótów, a następnie losowo wybrać jeden z tych;) – hemlocker

Odpowiedz

7

Można użyć metody shuffle w List::Util pomóc:

use List::Util qw(shuffle); 

... 

my @values = shuffle(values %hash); 
map { $hash{$_} = shift(@values) } (keys %hash); 
+1

'map' w kontekście nieważne jest wstręt. –

+0

Czy to tylko kwestia stylu, czy masz do tego techniczny sprzeciw? (po prostu ciekawy) – Mat

+1

Powrót, gdy 'map' zwrócił listę (nawet w pustym kontekście) to był prawdziwy problem. Te dni to tylko kwestia stylu. Niektórzy, jak ja, uważają, że abominacja polega na działaniu ubocznym funkcji. Zwłaszcza, gdy mamy konstrukcję, która jest tak krótka, że ​​nie używa efektu ubocznego: '$ hash {$ _} = shift @ wartości dla kluczy% hash;' –

4

Plasterek hash będzie najwyraźniejszy sposób do mnie:

#!/usr/bin/perl 

use strict; 
use warnings; 

use List::Util qw/shuffle/; 
use Data::Dumper; 

my %h = (
    this => 0, 
    is => 1, 
    a => 2, 
    test => 3, 
); 

@h{keys %h} = shuffle values %h; 

print Dumper \%h; 

Ma to wadę polegającą na tym, że wielkie hashe zajmują dużo pamięci, gdy wyciągniesz wszystkie swoje klucze i wartości. Bardziej wydajne (z punktu widzenia pamięci) rozwiązaniem byłoby:

#!/usr/bin/perl 

use strict; 
use warnings; 

use List::Util qw/shuffle/; 
use Data::Dumper; 

my %h = (
    this => 0, 
    is => 1, 
    a => 2, 
    test => 3, 
); 

{ #bareblock to cause @keys to be garbage collected 
    my @keys = shuffle keys %h; 

    while (my $k1 = each %h) { 
     my $k2 = shift @keys; 
     @h{$k1, $k2} = @h{$k2, $k1}; 
    } 
} 

print Dumper \%h; 

Kod ten ma tę zaletę, tylko konieczności duplikowania klawiszy (zamiast kluczy i wartości).

Poniższy kod nie losuje wartości (z wyjątkiem Perl 5.8.1, gdzie kolejność kluczy ma charakter losowy), ale miesza zamówienie. To ma korzyści z pracy w miejscu bez zbytniego dodatkowego zużycia pamięci:

#!/usr/bin/perl 

use strict; 
use warnings; 

use List::Util qw/shuffle/; 
use Data::Dumper; 

my %h = (
    this => 0, 
    is => 1, 
    a => 2, 
    test => 3, 
); 

my $k1 = each %h; 
while (defined(my $k2 = each %h)) { 
    @h{$k1, $k2} = @h{$k2, $k1}; 
    last unless defined($k1 = each %h); 
} 

print Dumper \%h; 
Powiązane problemy