在Perl中动态创建数组

时间:2010-08-23 06:35:10

标签: arrays perl

我想根据用户输入动态创建数组。例如,如果用户将输入设为3,则应创建名为@message1@message2@message3的三个数组。

我如何在Perl中完成?

4 个答案:

答案 0 :(得分:16)

别。相反,使用数组数组:

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

答案 1 :(得分:12)

我不得不问你为什么要这样做,因为这不是正确的方法。如果您有三个输入流,每个输入都需要存储为列表,则存储一个列表,这是一个列表列表(列表存储为数组引用):

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 Data Structures Cookbookperldoc perldsc) 为情况选择正确的数据结构,以及如何定义 它们。

答案 2 :(得分:4)

动态创建新的命名数组几乎不是一个好主意。启蒙书Higher-Order Perl的作者马克·多米努斯写了一篇three - part series,详细说明了这些陷阱。

对于这些数组,您需要考虑名称,因此请将它们放在哈希中:

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中使用引用的更多详细信息,请参阅以下文档:

答案 3 :(得分:2)

在编译语言中,变量没有名称。您在代码中看到的名称是与某些数字偏移相关联的唯一标识符。在message_2之类的标识符中,'2'仅用于使其成为唯一标识符。任何人都可以告诉您可以创建三个变量:message_125message_216message_343。只要你能告诉你应该把什么放进去,它们的工作方式和message_1 ......

一样好

变量的“名称”仅供您在编写代码时保持笔直。

动态语言通过不清除符号表来添加功能。但是符号表只是名称与值的关联。因为Perl为您提供如此便宜的列表和散列,所以不需要使用编程/逻辑方法来跟踪变量以允许灵活的运行时访问。

如果您看到自己命名列表@message1@message2,...... - 这些项目的参考顺序不同,那么这些名称也一样好:{{1 },$message[1],....

此外,由于符号表通常是从名称到偏移量(在堆栈或堆中)映射,因此它实际上并不比在哈希中找到的键值对更多。因此,散列对于查找更多不同的名称同样有效。

$message[2]

我的意思是,如果您愿意,您可以将放入词法变量的所有内容存储到范围的单个哈希中,如果您不介意写一下:$h{messages} = []; $h{replies} = []; 。但是你不会从Perl的隐式作用域管理中获益,而且跨语言,程序员更喜欢隐式作用域管理。

Perl允许进行符号操作,但多年来动态语言发现了混合的祝福。但是在Perl你有两个“观点”,给他们一个名字。因为您可以确定编译语言中的哪些代码可能比动态语言更好,所以已经确定更多的错误可以使用“编译透视图”来实现更多功能:因此您可以看到偏移管理的可用性并查找在核心Perl中给你的编译行为,如果你不需要,没有理由搞乱符号表。

动态创建数组非常简单:$h{variable_name}。将它分配到内存中的某个位置,当我们不知道要存储多少时,就像这样容易:

[]

一次创建列表列表就像以下一样简单:

push @message, [];

表示@message = map { [] } 1..$num_lists; 中的某些指定值。