12

这个页面上,它展示了如何初始化一个数组,如果你向下滚动一点,在名为“列表”的部分下,它会“解释”什么是列表以及它们与数组的不同之处。

除了它使用了一个与声明数组完全相同的示例,并且没有对其进行任何解释。

有什么不同?

4

8 回答 8

9

看看perldoc -q "list and an array"。最大的区别是数组是一个变量,但是 Perl 的所有数据类型(标量、数组和散列)都可以提供一个列表,它只是一组有序的标量。

考虑这段代码

use strict;
use warnings;

my $scalar = 'text';
my @array = (1, 2, 3);
my %hash = (key1 => 'val1', key2 => 'val2');

test();
test($scalar);
test(@array);
test(%hash);

sub test { printf "( %s )\n", join ', ', @_ }

输出这个

(  )
( text )
( 1, 2, 3 )
( key2, val2, key1, val1 )

Perl 子例程将列表作为其参数。在第一种情况下,列表是空的;在第二个中它有一个元素( $scalar);在第三个中,列表的大小与@array和 contains相同( $array[0], $array[1], $array[2], ...),在最后一个中,它的bug 是和 contains中元素数量的两倍%hash( 'key1', $hash{key1}, 'key2', $hash{key2}, ...)

很明显,该列表可以通过多种方式提供,包括标量变量、标量常量和子例程调用的结果的混合,例如

test($scalar, $array[1], $hash{key2}, 99, {aa => 1, bb => 2}, \*STDOUT, test2())

我希望很清楚这样的列表与数组有很大不同。

将数组视为列表变量会有所帮助吗?区分标量文字和标量变量很少有问题。例如:

my $str = 'string';
my $num = 99;

很明显,'string'and99是文字,而$strand$num是变量。这里的区别是一样的:

my @numbers = (1, 2, 3, 4);
my @strings = qw/ aa bb cc dd /;

其中(1, 2, 3, 4)qw/ aa bb cc dd /是列表文字,而@numbers@strings是变量。

于 2012-12-22T20:00:12.693 回答
8

实际上,这个问题在Perl 的 FAQ中得到了很好的回答。列表是在 Perl 源代码中组织数据的(一种)方法。数组是存储数据的一种类型;哈希是另一个。

区别在这里很明显:

my @arr = (4, 3, 2, 1);
my $arr_count  = @arr;
my $list_count = (4, 3, 2, 1);

print $arr_count, "\n"; # 4
print $list_count;      # 1

乍一看,这里有两个相同的列表。但是请注意,只有分配给@arr变量的那个才能通过标量分配正确计数。$list_count商店 1 - 使用运算符评估表达式的结果(comma基本上为我们提供了该枚举中的最后一个表达式 - 1)。

请注意,列表运算符/函数和数组运算符/函数之间存在细微(但非常重要)的区别:前者是杂食动物,因为它们不会更改源数据,而后者则不会。例如,您可以安全地切片并加入您的列表,如下所示:

print join ':', (4,2,3,1)[1,2]; 

...但试图“弹出”它会给你一个很有说服力的信息:

pop (4, 3, 2, 1);
### Type of arg 1 to pop must be array (not list)...
于 2012-12-22T09:43:54.840 回答
8

数组是一种变量。它在单调递增的索引处包含 0 个或多个标量。例如,以下创建数组@a

my @a;

作为变量,您可以操作数组。您可以添加元素,更改元素的值等。


“列表”意味着很多东西。它的两个主要用途是引用列表值和列表运算符的实例。

列表值是堆栈上零个或多个标量的有序集合。例如,以下代码中的 sub 返回要分配给@a(数组)的列表。

my @a = f();

列表值不能被操纵;它们被传递给它们的任何操作员全部吸收。它们就是在 subs 和操作符之间传递值的方式。


列表运算符 ( ,) 是一个 N 元运算符*,它依次计算其每个操作数。在列表上下文中,列表运算符返回一个列表,该列表由其操作数返回的列表的合并组成。例如,以下代码段中的列表运算符返回由数组的所有元素组成的列表值@a@b

my @c = ( @a, @b );

(顺便说一句,parens 不会创建列表。它们只是为了覆盖优先级。)

您不能操纵列表运算符,因为它是代码。


* - 文档说它是一个二元运算符(至少在标量上下文中),但事实并非如此。

于 2012-12-22T18:06:14.810 回答
3

差异的简单演示。

sub getarray{ my @x = (2,4,6); return @x; }

sub getlist { return (2,4,6); }

现在,如果你这样做:

 my @a = getarray();
 my @b = getlist();

然后@a@b都将包含相同的值 - 列表(2,4,6)。但是,如果您这样做:

my $a = getarray();
my $b = getlist();

然后$a将包含值 3,而$b将包含值 6。

所以是的,您可以说数组是包含列表值的变量,但这并不能说明全部情况,因为数组和文字列表有时的行为完全不同。

于 2012-12-22T21:23:42.457 回答
3

列表是逗号分隔值 (csv) 或表达式 (cse)。数组(和哈希)是容器。

可以通过列表初始化数组或哈希:

@a = ("profession", "driver", "salary", "2000");
%h = ("profession", "driver", "salary", "2000");

可以返回一个列表:

sub f {
    return "moscow", "tel-aviv", "madrid";
}

($t1, $t2, $t3) = f();
print "$t1 $t2 $t3\n";

($t1, $t2, $t3) 是标量容器 $t1, $t2, $t3 的列表。

列表是编写 perl 表达式的一种形式(语法的一部分),而数组是数据结构(内存位置)。

于 2013-03-18T09:18:18.567 回答
2

列表和数组之间的区别让很多人感到困惑。Perl 本身错误地命名了它的内置函数wantarray():“这个函数应该被命名为 wantlist() 。” perlfaq4 中有一个答案,“列表和数组有什么区别?” ,但这并没有结束我的困惑。

我现在相信这些是真的:

  • 标量上下文中的数组成为其元素的计数。
  • 标量上下文中的逗号运算符返回最后一个元素。
  • 您不能引用列表;\(2, 4, 6)返回对列表中标量的引用列表。您可以使用[2, 4, 6]来引用匿名数组。
  • 如果您制作列表切片,则可以索引列表(以获取其第n个元素)而不制作数组,(2, 4, 6)[1]4 也是如此。

但是如果我想计算列表中的元素,或者获取数组的最后一个元素怎么办?我应该以某种方式在数组和列表之间进行转换吗?

您始终可以使用语法将列表转换为数组。[...]计算列表中元素的一种方法是创建一个匿名数组,然后立即在标量上下文中取消引用它,如下所示:

sub list { return qw(carrot stick); }
my $count = @{[list()]};
print "Count: $count\n";  # Count: 2

另一种方法是使用列表赋值运算符,如下所示:

sub list { return qw(carrot stick); }
my $count = (()=list());
print "Count: $count\n";  # Count: 2

这段代码中没有数组,但是列表赋值运算符返回被赋值的事物的数量。我将它们分配给一个空的变量列表。在代码高尔夫中,我编写()=$str=~/reg/g来计算某个字符串中的正则表达式匹配。

您无需将数组转换为列表,因为列表上下文中的数组已经是列表。如果您想要数组的最后一个元素,只需说$array[-1].

逗号运算符将返回列表的最后一个元素,但我不能使用它来获取数组的最后一个元素。如果我((),@array)在标量上下文中说,那么@array是在标量上下文中,我得到了计数。

您无需创建数组来索引列表。您可以创建一个匿名数组,如 中[list()]->[1],也可以创建一个列表切片,如中(list())[1]。我在使用列表切片时遇到了麻烦,因为它们有不同的语法。列表切片需要括号!在 C 或 Python 或 Ruby 中,func()[1]会对函数的返回值做数组索引,但在 Perl 中,func()[1]是语法错误。你必须说(func())[1]

例如,我想打印数组中第三大的数字。因为我很懒,所以我对数组进行排序并取倒数第三个元素:

my @array = (112, 101, 114, 108, 32, 104, 97, 99, 107);
print +(sort { $a <=> $b } @array)[-3], "\n";  # prints 108

一元+防止 print() 函数窃取我的括号。

您可以在数组上使用列表切片,如(@array)[1]. 这是有效的,因为数组是一个列表。列表和数组的区别在于数组可以做$array[1].

于 2015-04-07T01:34:10.393 回答
0

数组与列表

列表是一种不同于数组的数据结构。

最大的区别在于直接访问与顺序访问的思想。数组允许两者;直接和顺序访问,而列表只允许顺序访问。这是因为这些数据结构存储在内存中的方式。

此外,列表的结构不像数组那样支持数字索引。而且,元素不需要像数组那样在内存中彼此相邻分配。

数组

数组是项的有序集合,其中数组中的每个项都有一个索引。

于 2019-02-19T07:41:43.897 回答
-1

这是我关于印记和背景的回答

但主要区别在于:

数组有一个scalar-context-valuelike count of elements

列表有一个scalar-context-valuelike LAST element in list

所以,你需要了解goat-operator=()=

用法?

perl -e '$s =()= qw(a b c); print $s' # uh? 3? (3 elements, array context)

perl -e '$s = qw(a b cLastElementThatYouSee); print $s' # uh? cLastElementThatYouSee? (list context, last element returned)

如您所见,=()=将上下文更改为array

于 2012-12-22T11:28:40.053 回答