Если у меня есть хеш в Perl, который содержит полные и последовательные целочисленные отображения (т.е., все ключи от от 0 до n отображаются на чем-то, никаких ключах за пределами этого), там средство преобразования этого к Массиву?
Я знаю, что мог выполнить итерации по парам ключ/значение и разместить их в новый массив, но что-то мне подсказывает, что должно быть встроенное средство выполнения этого.
Если исходный источник данных - хэш:
# first find the max key value, if you don't already know it:
use List::Util 'max';
my $maxkey = max keys %hash;
# get all the values, in order
my @array = @hash{0 .. $maxkey};
Или если исходный источник данных - хэш:
my $maxkey = max keys %$hashref;
my @array = @{$hashref}{0 .. $maxkey};
Это легко проверить на следующем примере:
my %hash;
@hash{0 .. 9} = ('a' .. 'j');
# insert code from above, and then print the result...
use Data::Dumper;
print Dumper(\%hash);
print Dumper(\@array);
$VAR1 = {
'6' => 'g',
'3' => 'd',
'7' => 'h',
'9' => 'j',
'2' => 'c',
'8' => 'i',
'1' => 'b',
'4' => 'e',
'0' => 'a',
'5' => 'f'
};
$VAR1 = [
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j'
];
Вы можете извлечь все значения из хэша с помощью функции values
:
my @vals = values %hash;
Если вы хотите, чтобы они были в определенном порядке, вы можете поместить ключи в желаемый порядок, а затем возьмите хэш-срез из этого:
my @sorted_vals = @hash{sort { $a <=> $b } keys %hash};
Хорошо, это не очень "встроено", но работает. Это также ИМХО предпочтительнее любого решения, связанного с «сортировкой», поскольку оно быстрее.
map { $array[$_] = $hash{$_} } keys %hash; # Or use foreach instead of map
В противном случае, менее эффективно:
my @array = map { $hash{$_} } sort { $a<=>$b } keys %hash;
Это оставит ключи, не определенные в % hashed_keys
как undef
:
# if we're being nitpicky about when and how much memory
# is allocated for the array (for run-time optimization):
my @keys_arr = (undef) x scalar %hashed_keys;
@keys_arr[(keys %hashed_keys)] =
@hashed_keys{(keys %hashed_keys)};
И, если вы используете ссылки:
@{$keys_arr}[(keys %{$hashed_keys})] =
@{$hashed_keys}{(keys %{$hashed_keys})};
Или, что более опасно, поскольку предполагается, что то, что вы сказали, правда (это не всегда может быть правдой… Просто скажите!):
@keys_arr = @hashed_keys{(sort {$a <=> $b} keys %hashed_keys)};
Но это вроде как не относится к делу. Если они изначально были проиндексированы целыми числами, почему они сейчас в хэше?
Комбинация ответов FM и Ether позволяет избежать определения ненужного скаляра:
my @array = @hash{ 0 .. $#{[ keys %hash ]} };
Самое интересное, что в отличие от скалярного
подхода, $#
работает даже в том маловероятном случае, если индекс первого элемента по умолчанию, $[
, ненулевой.
Конечно, это означало бы написать что-то глупое и запутанное вроде:
my @array = @hash{ $[ .. $#{[ keys %hash ]} }; # Not recommended
Но тогда всегда есть отдаленный шанс, что это кому-то понадобится (поморщитесь)...
Perl не предоставляет встроенных средств для решения вашей проблемы.
Если вы знаете, что ключи охватывают определенный диапазон 0..N
, вы можете использовать этот факт:
my $n = keys(%hash) - 1;
my @keys_and_values = map { $_ => $hash{$_} } 0 .. $n;
my @just_values = @hash{0 .. $n};
Как сказал DVK, встроенного способа нет, но это поможет:
my @array = map {$hash{$_}} sort {$a <=> $b} keys %hash;
или этот:
my @array;
keys %hash;
while (my ($k, $v) = each %hash) {
$array[$k] = $v
}
тест, чтобы увидеть, что быстрее, я думаю, будет вторым .