Я создаю пять массивов на языке Perl (null, null, 32, 54, null, 59). Поэтому я сначала помещаю известные мне значения в определенный индекс, а остальные заполняю нулевым значением. Я делаю это вот так

my @p0_series, @p1_series;
$p0_series[2] = "test";
$p1_series[3] = "string";
$p2_series[2] = "hello";
$p3_series[2] = "hi";
for($a = 0; $a < 5; $a++) {
  if(!defined $p0_series[$a]) {
   $p0_series[$a] = null;
  }

  if(!defined $p1_series[$a]) {
   $p1_series[$a] = null;
  }

  if(!defined $p3_series[$a]) {
   $p3_series[$a] = null;
  }

  if(!defined $p4_series[$a]) {
   $p4_series[$a] = null;
  }

  if(!defined $p5_series[$a]) {
   $p5_series[$a] = null;
  }
}

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

for($a=0: $a <5; $a++ ){
if(!defined $p$i_series[$a] ) {
 #  assign values;
}
}

Что не работает. Я новичок в Perl, любая помощь приветствуется. Можно ли более простым способом присвоить нулевое значение всем элементам undef в массиве?

1
Annapoorni D 31 Дек 2013 в 14:34

2 ответа

Лучший ответ

В Perl нет null, но есть undef - что, кстати, является значением по умолчанию для неназначенных элементов в массивах:

my @array = (undef, undef, 32, 54, undef, 59);

Создает такую ​​же структуру, как:

my @array;
$array[2] = 32;
$array[3] = 54;
$array[5] = 59;

Нет необходимости назначать другие поля для undef самостоятельно.

Если вы пытаетесь присвоить значение по умолчанию элементам, которые в настоящее время являются undef, вы можете написать что-то вроде этого (но обратите внимание на ограничения ниже):

defined or $_ = "default" for @array;

В Perl 5.10 или новее вы можете использовать оператор defined-or //:

$_ //= "default" for @array

Чтобы назначить значения по умолчанию для нескольких массивов:

$_ //= "default" for @array, @other_array

Если вы хотите установить массив определенной длины, вы можете сделать $#array = $length - 1, так что это фактически определяет наивысший индекс. Это удаляет записи из более длинных массивов. Для более коротких массивов все вновь созданные записи будут undef.


Здесь есть небольшая проблема: Perl имеет два вида undef:

  • Скаляры могут содержать значение undef, например my $foo = undef.

    Это тот случай, если мы инициализируем сразу весь массив, например my @array = (undef, undef, 32, 54, undef, 59).

  • Неназначенные значения в массивах или хэшах разделяют свой скаляр undef, который доступен только для чтения.

    Это тот случай, когда мы инициализируем массив, присваивая только некоторые индексы, например $array[4] = 2.

Обычно это не проблема, но в цикле for $_ является псевдонимом для текущего скаляра, который в нашем случае доступен только для чтения. Поэтому мы не всегда можем делать $_ //= "default" for @array, но должны либо:

  • Назначьте непосредственно в элемент массива, который создает назначаемый скаляр в этом слоте:

    $array[$_] //= "default" for 0 .. $#array;
    

    Для нескольких массивов:

    for my $ref (\@array, \@other_array) {
      $ref->[$_] //= "default" for 0 .. $#$ref;
    }
    
  • Не назначайте элемент и вместо этого создайте копию массива со значениями по умолчанию:

    @array = map { $_ // "default" } @array;
    

    Для нескольких массивов:

    @$_ = map { $_ // "default" } @$_ for \@array, \@other_array;
    

    Хотя я считаю это более элегантным, с этим могут возникнуть некоторые проблемы, поскольку каждый элемент массива копируется.

4
amon 2 Янв 2014 в 11:05

Согласен, но на всякий случай в perl вы также можете создать имя переменной времени выполнения. Как и в вашем случае

Если (! определено $ p $ i_series [$ a])

Если (! определено $ {"p $ i". "_ series"} [$ a])

Это должно выполнить работу и создать переменную $ p1_series [$ a], $ p2_series [$ a] и т. Д.

-2
Gaurav 2 Янв 2014 в 08:25