shuffle
рандомизирует порядок. Таким образом, эту операцию нельзя отменить (так же, как вы не можете приготовить яичницу, положив ее в холодильник). Но мы можем использовать хитрость: перетасовать индексы вместо значений:
my @items = 'a' .. 'z'; # things we want to shuffle
my @shuffled_idxs = shuffle 0 .. $#items;
my @shuffled = @items[@shuffled_idxs]; # using a slice to do the actual shuffling
Из @shuffled_idxs
мы можем создать массив, позволяющий выполнять обратный поиск:
my @reverse_idxs;
$reverse_idxs[$shuffled_idxs[$_]] = $_ for 0 .. $#shuffled_idxs;
# now we can use a slice to reverse the shuffling:
my @reversed = @shuffled[@reverse_idxs];
Когда мы выводим @items
, @shuffled
и @reversed
, мы можем получить следующий вывод:
abcdefghijklmnopqrstuvwxyz
hyaxruvnogekdzjmbpilstcqfw
abcdefghijklmnopqrstuvwxyz
Это отлично работает для массивов. Ваш пример немного отличается, потому что у вас есть такие последовательности, как
a b b b c c
и вы хотите сделать хэш { a => 1, b => 3, c => 2 }
. Это можно сделать без перетасовки, используя вместо этого обычный подсчет:
my %reversed;
$reversed{$_}++ for @shuffled_roles;
Однако вы пропускаете роли, которые сопоставляются с нулем. Поскольку этой информации больше нет в массиве ролей, ее нельзя воссоздать.
person
amon
schedule
10.09.2013