Динамическое создание массивов в Perl - PullRequest
8 голосов
/ 23 августа 2010

Я хочу создавать массивы динамически на основе пользовательского ввода.Например, если пользователь вводит данные как 3, необходимо создать три массива с именами @message1, @message2 и @message3.

Как мне это сделать в Perl?

Ответы [ 4 ]

16 голосов
/ 23 августа 2010

Не. Вместо этого используйте массив массивов:

my @message;
my $input = 3;
for my $index ( 0..$input-1 ) {
    $message[$index][0] = "element 0";
    $message[$index][1] = 42;
}
print "The second array has ", scalar( @{ $message[1] } ), " elements\n";
print "They are:\n";
for my $index ( 0..$#{ $message[1] } ) {
    print "\t", $message[1][$index], "\n";
}

Некоторые полезные правила на http://perlmonks.org/?node=References+quick+reference

12 голосов
/ 23 августа 2010

Я должен спросить, почему вы хотите это сделать, потому что это не правильный путь. Если у вас есть три потока ввода, каждый из которых необходимо сохранить в виде списка, сохраните один список, который представляет собой список списков (где списки хранятся как ссылки на массивы ):

my @input = (
    [ 'data', 'from', 'first', 'user' ],
    [ qw(data from second user) ],
    [ qw(etc etc etc) ],
);

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

my %input = (
    senthil => [ 'data', 'from', 'first', 'user' ],
    ether => [ qw(data from second user) ],
    apu => [ qw(etc etc etc) ],
);

Для получения дополнительной информации см. Руководство по структурам данных Perl (perldoc perldsc). о выборе правильной структуры данных для ситуации и как определить их.

4 голосов
/ 23 августа 2010

Создание новых именованных массивов динамически почти никогда не является хорошей идеей. Марк Доминус, автор просвещающей книги Perl высшего порядка , написал три - часть серия детализация подводных камней.

У вас есть имена для этих массивов, поэтому поместите их в хеш:

sub create_arrays {
  my($where,$n) = @_;

  for (1 .. $n) {
    $where->{"message$_"} = [];
  }
}

Для быстрого примера, который показывает структуру, код ниже

my $n = @ARGV ? shift : 3;

my %hash;
create_arrays \%hash, $n;

use Data::Dumper;
$Data::Dumper::Indent = $Data::Dumper::Terse = 1;
print Dumper \%hash;

выходы

$ ./prog.pl
{
  'message2' => [],
  'message3' => [],
  'message1' => []
}

Указав другое количество массивов, получим

$ ./prog.pl 7
{
  'message2' => [],
  'message6' => [],
  'message5' => [],
  'message4' => [],
  'message3' => [],
  'message1' => [],
  'message7' => []
}

Порядок ключей выглядит забавно, потому что они внутри хеша, неупорядоченной структуры данных.

Напомним, что [] создает ссылку на новый анонимный массив, поэтому, например, чтобы добавить значения в message2, вы должны написать

push @{ $hash{"message2"} }, "Hello!";

Чтобы напечатать это, вы должны написать

print $hash{"message2"}[0], "\n";

Может быть, вместо этого вы хотите знать, как долго все массивы:

foreach my $i (1 .. $n) {
  print "message$i: ", scalar @{ $hash{"message$i"} }, "\n";
}

Подробнее о том, как использовать ссылки в Perl, см. В следующей документации:

2 голосов
/ 23 августа 2010

В скомпилированных языках переменные не имеют имени. Имя, которое вы видите в коде, представляет собой уникальный идентификатор, связанный с некоторым числовым смещением. В идентификаторе, подобном message_2, '2' служит только для того, чтобы сделать его уникальным идентификатором. Любой может сказать, что вы можете сделать три переменные: message_125, message_216 и message_343. Пока вы можете сказать, что вы должны вкладывать в то, что они работают так же хорошо, как message_1 ...

«Имя» переменной предназначено только для того, чтобы вы оставляли их прямыми во время написания кода.

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

Скорее всего, если вы видите списки имен @message1, @message2, ... - где элементы отличаются только по порядку ссылок, эти имена так же хороши: $message[1], $message[2] , ....

Кроме того, поскольку таблицы символов обычно отображаются из имени в смещение (либо в стеке, либо в куче), это на самом деле не намного больше, чем пара ключ-значение, которую вы найдете в хэше . . Таким образом, хеши работают так же хорошо, чтобы искать более четкие имена.

$h{messages} = [];
$h{replies}  = [];

Я имею в виду, на самом деле, если вы хотите, вы можете хранить все, что вы помещаете в лексическую переменную, в один хеш для области, если вы не возражаете написать: $h{variable_name} для всего. Но вы не получите преимущества неявного управления областями Perl, и программисты предпочитают неявное управление областями в разных языках.

Perl допускает символические манипуляции, но с годами динамические языки обнаружили, что это смешанное благословение. Но в Perl у вас есть обе «перспективы», чтобы дать им имя. Поскольку вы можете определить, какой код в скомпилированном языке, вероятно, будет работать лучше, чем динамический язык, было определено, что без ошибок можно использовать «скомпилированную перспективу» для большего количества вещей: так, как вы можете видеть с доступностью смещения и посмотрите скомпилированное поведение, данное вам в ядре Perl, нет причин возиться с таблицей символов, если вам не нужно.

Динамическое создание массива так же просто, как: []. Присвоить это место в памяти, когда мы не знаем, сколько мы хотим сохранить, так же просто, как:

push @message, [];

И создать список списков одновременно так же просто, как:

@message = map { [] } 1..$num_lists;

для некоторого указанного значения в $num_lists.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...