Как перемешать значения в хэше? - PullRequest
5 голосов
/ 13 июля 2011

У меня есть хэш идентификаторов строк.Каков наилучший способ перетасовать идентификаторы?

Например, мой хэш назначает следующие идентификаторы:

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

Теперь я хотел бы случайным образом перемешать это.Пример результата будет:

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

Ответы [ 2 ]

7 голосов
/ 13 июля 2011

Вы можете использовать метод shuffle в List::Util, чтобы помочь:

use List::Util qw(shuffle);

...

my @values = shuffle(values %hash);
map { $hash{$_} = shift(@values) } (keys %hash);
4 голосов
/ 13 июля 2011

Самый понятный способ для меня - ломтик хеша:

#!/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;

Это имеет недостаток в том, что огромные хэши занимают много памяти, когда вы извлекаете все их ключи и значения. Более эффективное (с точки зрения памяти) решение было бы:

#!/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;

Преимущество этого кода состоит в том, что ему приходится только дублировать ключи (а не ключи и значения).

Следующий код не рандомизирует значения (кроме Perl 5.8.1 , где порядок ключей гарантированно является случайным), но он смешивает порядок. Преимущество работы на месте без чрезмерного использования памяти:

#!/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;
...