В чем разница между списками и массивами?
На странице 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