Perl, преобразуйте хеш для выстраивания

Если у меня есть хеш в Perl, который содержит полные и последовательные целочисленные отображения (т.е., все ключи от от 0 до n отображаются на чем-то, никаких ключах за пределами этого), там средство преобразования этого к Массиву?

Я знаю, что мог выполнить итерации по парам ключ/значение и разместить их в новый массив, но что-то мне подсказывает, что должно быть встроенное средство выполнения этого.

20
задан Mike 25 May 2010 в 18:09
поделиться

8 ответов

Если исходный источник данных - хэш:

# 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'
        ];
22
ответ дан 29 November 2019 в 22:58
поделиться

Вы можете извлечь все значения из хэша с помощью функции values ​​ :

my @vals = values %hash;

Если вы хотите, чтобы они были в определенном порядке, вы можете поместить ключи в желаемый порядок, а затем возьмите хэш-срез из этого:

my @sorted_vals = @hash{sort { $a <=> $b } keys %hash};
16
ответ дан 29 November 2019 в 22:58
поделиться

Хорошо, это не очень "встроено", но работает. Это также ИМХО предпочтительнее любого решения, связанного с «сортировкой», поскольку оно быстрее.

map { $array[$_] = $hash{$_} } keys %hash; # Or use foreach instead of map

В противном случае, менее эффективно:

my @array = map { $hash{$_} } sort { $a<=>$b } keys %hash;
13
ответ дан 29 November 2019 в 22:58
поделиться

Это оставит ключи, не определенные в % 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)};

Но это вроде как не относится к делу. Если они изначально были проиндексированы целыми числами, почему они сейчас в хэше?

2
ответ дан 29 November 2019 в 22:58
поделиться

Комбинация ответов FM и Ether позволяет избежать определения ненужного скаляра:

my @array = @hash{ 0 .. $#{[ keys %hash ]} };

Самое интересное, что в отличие от скалярного подхода, $# работает даже в том маловероятном случае, если индекс первого элемента по умолчанию, $[, ненулевой.

Конечно, это означало бы написать что-то глупое и запутанное вроде:

my @array = @hash{ $[ .. $#{[ keys %hash ]} };   # Not recommended

Но тогда всегда есть отдаленный шанс, что это кому-то понадобится (поморщитесь)...

0
ответ дан 29 November 2019 в 22:58
поделиться
@a = @h{sort { $a <=> $b } keys %h};
0
ответ дан 29 November 2019 в 22:58
поделиться

Perl не предоставляет встроенных средств для решения вашей проблемы.

Если вы знаете, что ключи охватывают определенный диапазон 0..N , вы можете использовать этот факт:

my $n = keys(%hash) - 1;
my @keys_and_values = map { $_ => $hash{$_} } 0 .. $n;
my @just_values     = @hash{0 .. $n};
4
ответ дан 29 November 2019 в 22:58
поделиться

Как сказал DVK, встроенного способа нет, но это поможет:

my @array = map {$hash{$_}} sort {$a <=> $b} keys %hash;

или этот:

my @array;

keys %hash;

while (my ($k, $v) = each %hash) {
    $array[$k] = $v
}

тест, чтобы увидеть, что быстрее, я думаю, будет вторым .

0
ответ дан 29 November 2019 в 22:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: