В чем разница между списками и массивами?

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

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

в чем разница?

7 ответов


посмотри 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 и содержит ( $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 переменные. И различие здесь то же самое:--26-->

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

здесь (1, 2, 3, 4) и qw/ aa bb cc dd / список литералов, в то время как @numbers и @strings переменные.


массив-это тип переменной. Он содержит 0 или более элементов, состоящих из неотрицательного целочисленного ключа и скалярного значения. Например,

my @a;

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


"список" означает много вещей. Два основных использования для него-ссылаться на значения списка и операторы списка.

значение списка представляет собой упорядоченную коллекцию нулевых или более скаляров в стеке. Например, sub в следующем коде возвращает список, который должен быть назначен @a (массив).

my @a = f();

значения списка нельзя манипулировать; они поглощаются целиком любым оператором, которому они передаются. Это просто то, как значения передаются между Sub и операторами.


оператор list-это оператор N-ary*, который поочередно вычисляет каждый из своих операндов. В контексте списка оператор list возвращает список, состоящий из объединения списков возвращается его операндами. Например, следующий оператор list возвращает значение list, состоящее из всех элементов массивов @a и @b:

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

(кстати, родители не создают списки. Они здесь только для того, чтобы отменить приоритет.)

вы не можете манипулировать оператором списка, так как это код.


* - документы говорят, что это двоичный оператор (по крайней мере, в скалярном контексте), но это не так.


на самом деле, на этот вопрос довольно хорошо ответили в FAQ Perl. Списки-это (один из) методов организации данных в исходном коде 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 переменная правильно подсчитывается скаляром назначение. The $list_count stores 1-результат оценки выражения с помощью comma оператор (который в основном дает нам последнее выражение в этом перечислении - 1).

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

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

... но пытаюсь "pop" это даст вам довольно красноречивое сообщение:

pop (4, 3, 2, 1);
### Type of arg 1 to pop must be array (not list)...

простая демонстрация разницы.

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

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

теперь, если вы делаете что-то вроде этого:

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

затем @a и @b оба будут содержать одно и то же значение - list (2,4,6). Однако, если вы это сделаете:

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

затем $a будет содержать значение 3, в то время как $b будет содержать значение 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, в $Т3) представляет собой список скалярных контейнеров $Т1 $Т2, $Т3.

списки-это форма написания выражений perl (часть синтаксиса), а массивы-это структуры данных (местоположения памяти).


разницу между списками и массивами смущает многих. Сам Perl ошибся на misnaming ее функции строение wantarray(): "вместо этого эту функцию следовало бы назвать wantlist ()."Есть ответ в perlfaq4, " в чем разница между списком и массивом?", но это не конец моего замешательства.

теперь я верю, что это правда:

  • массив в скалярном контексте становится считать его элементы.
  • на оператор запятая в скалярном контексте возвращает последний элемент.
  • вы не можете сделать ссылку на список;\(2, 4, 6) возвращает список ссылок на скаляры в списке. Вы можете использовать [2, 4, 6] сделать ссылку на анонимный массив.
  • вы можете индексировать список (чтобы получить ее nth элемент) без создания массива, если вы делаете срез списка, так что (2, 4, 6)[1] is 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

здесь нет массив в этом коде, но оператор присваивания списка возвращает количество назначаемых вещей. Я назначаю их пустому списку переменных. В коде golf я пишу ()=$str=~/reg/g для подсчета совпадений регулярных выражений в некоторой строке.

не нужно преобразование массива в список, потому что массив в контексте списка уже список. Если вам нужен последний элемент массива, просто скажите $array[-1].

оператор запятой вернет последнее элемент списка, но я не могу использовать его для получения последнего элемента массива. Если я скажу ((),@array) в скалярном контексте, то @array в скалярном контексте и я понимаю, граф.

вам не нужно создавать массив для список. Вы можете сделать анонимный массив, как в [list()]->[1], или вы можете сделать срез списка, например,(list())[1]. У меня были проблемы с срезами списка, потому что у них другой синтаксис. Срез списка нуждается в скобках! В C или Python или Ruby,func()[1] будет делать индекс массива для возвращаемого значения функции, но в Perl,func()[1] ошибка синтаксиса. Вы должны сказать (func())[1].

например, я хочу напечатать 3-е наибольшее число в массиве. Поскольку я ленив, я сортирую массив и беру 3-й последний элемент:

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].


вот мой ответ о сигилах и контексте

но главное отличие заключается в следующем:

массивы scalar-context-value как count of elements.

списки есть scalar-context-value как LAST element in list.

Итак, вы должны знать о!--5-->: =()=.

использования?

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