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

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

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

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

Ответ 1

Взгляните на 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 являются переменными. И различие здесь одно и то же:

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

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

Ответ 2

Собственно, на этот вопрос довольно хорошо ответил 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)...

Ответ 3

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

my @a;

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


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

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

my @a = f();

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


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

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

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

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


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

Ответ 4

Простая демонстрация различий.

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.

Итак, вы можете сказать, что массивы - это переменные, содержащие значения списка, но это не говорит всю историю, потому что массивы и списки букв ведут себя по-разному.

Ответ 5

Списки представляют собой значения, разделенные запятыми (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-выражений (часть синтаксиса), тогда как массивы представляют собой структуры данных (ячейки памяти).

Ответ 6

Различие между списками и массивами сбивает с толку многих. 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].

Например, я хочу напечатать 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].

Ответ 7

Массив против списка

Список - это другой тип структуры данных из массива.

Самое большое отличие заключается в идее прямого доступа и последовательного доступа. Массивы позволяют оба; прямой и последовательный доступ, а списки разрешают только последовательный доступ. И это потому, что эти структуры данных хранятся в памяти.

Кроме того, структура списка не поддерживает числовой индекс, как массив. И элементы не должны быть расположены рядом друг с другом в памяти, как массив.

Массивы

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

enter image description here

Списки

Это набор элементов (называемых узлами), упорядоченных в линейной последовательности.

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

enter image description here

Ответ 8

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

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

массивы имеют 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