【问题标题】:What is the difference between lists and arrays?列表和数组有什么区别?
【发布时间】:2012-12-09 17:14:47
【问题描述】:

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

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

有什么区别?

【问题讨论】:

  • 您的引用具有误导性。它说数组只是一组标量,而它的意义远不止这些
  • 而且还比这更少,因为#!math {2, 3, 2} 不是一个集合。
  • @darch:我认为 set 的数学概念在这里无关紧要。
  • 我认为您所指的那个页面相当混乱。 “列表实际上是一种特殊类型的数组”在我看来是废话。 Perl 有三种类型的变量:标量、数组和散列。列表就像它们听起来的样子:标量列表。就像您有一个购物清单一样,它是您需要购买的物品的清单。无需复杂化。

标签: arrays perl list


【解决方案1】:

其实这个问题在Perl's 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)...

【讨论】:

  • 根据定义,数组是保存列表的变量。因此,就所有实际问题而言,它们确实是一回事。
  • @aerovistae 不,它们显然不是一回事。列表和数组的行为可能完全不同(如上),掌握差异对于编写无错误的 Perl 至关重要。
  • 谈论列表计数是无意义且具有误导性的。我不赞成。
  • 您的最后一个示例存在严重缺陷。将 4 更改为 $x 并且不会出现错误(在 5.16 中)。您的示例并未显示您声称的功能。
  • @Aerovistae:数组和列表不再是标量变量和字符串或数字“相同的东西”。
【解决方案2】:

here my answer about sigils and context

但主要区别在于:

数组有一个scalar-context-value,比如count of elements

列表有一个scalar-context-value,比如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

【讨论】:

    【解决方案3】:

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

    my @a;
    

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


    “列表”有很多含义。它的两个主要用途是引用列表值和列表运算符的实例。

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

    my @a = f();
    

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


    列表运算符 (,) 是一个 N 元运算符*,它依次计算其每个操作数。在列表上下文中,列表运算符返回一个列表,该列表由其操作数返回的列表的合并组成。比如下面sn-p中的list操作符,返回一个列表值,由数组@a@b的所有元素组成:

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

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

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


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

    【讨论】:

    • 什么是列表运算符?逗号?逗号不是也存在于数组中吗?以及散列?
    • @Aerovistae,Re "什么是列表运算符?",逗号运算符的别称。 /// Re "逗号不是也出现在数组中,还有散列吗?",什么?
    • 哈希和数组中都可能包含逗号:(1, 2)("key" => "value", "key2" => "value2")。我不知道我的意思是什么了。叹。 Perl 不同。
    • 我想我的观点是,很难判断逗号运算符何时将仅分隔事物以及何时导致列表仅返回最后一个元素。
    • @Aerovistae,这些不是数组或散列;这两个都是逗号运算符的实例(根据上下文返回最后一个值或所有值。)数组和散列是变量的类型,它们不是变量。
    【解决方案4】:

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

    考虑这段代码

    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 子例程采用 list 作为其参数。在第一种情况下,列表是空的;在第二个中,它有一个元素( $scalar);在第三个列表中,列表大小与@array 相同,包含( $array[0], $array[1], $array[2], ...),在最后一个列表中,它是%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'99 是文字,而$str$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 是变量。

    【讨论】:

    • 天哪,这是两倍的错误!
    【解决方案5】:

    差异的简单演示。

    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。

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

    【讨论】:

      【解决方案6】:

      列表是逗号分隔的值 (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 表达式的一种形式(语法的一部分),而数组是数据结构(内存位置)。

      【讨论】:

        【解决方案7】:

        列表和数组的区别让很多人感到困惑。 Perl 本身错误地命名了它的内置函数wantarray():“这个函数应该被命名为wantlist()。” perlfaq4 中有一个答案,"What is the difference between a list and an array?",但这并没有结束我的困惑。

        我现在相信这些都是真的:

        • 标量上下文中的数组成为其元素的计数。
        • 标量上下文中的逗号运算符返回最后一个元素。
        • 您不能引用列表; \(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]

        【讨论】:

          【解决方案8】:

          数组与列表

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

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

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

          数组

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

          【讨论】:

          • 在所有事物调用列表中,链表是最不可能被讨论的事物(在 Perl 上下文中)。
          猜你喜欢
          • 1970-01-01
          • 2010-10-12
          • 1970-01-01
          相关资源
          最近更新 更多