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