Найти размер массива в Perl

199

Кажется, я нашел несколько разных способов найти размер массива. В чем разница между этими тремя методами?

my @arr = (2);
print scalar @arr; # First way to print array size

print $#arr; # Second way to print array size

my $arrSize = @arr;
print $arrSize; # Third way to print array size
  • 13
    другие способы: print 0+@arr , print "".@arr , print ~~@arr
  • 3
    @mob, гм, можно избежать "".@arr поскольку "@arr" делает что-то совсем другое.
Показать ещё 3 комментария
Теги:

10 ответов

207
Лучший ответ

Первый и третий способы одинаковы: они оценивают массив в скалярном контексте. Я бы счел, что это стандартный способ получить размер массива.

Второй способ фактически возвращает последний индекс массива, который не является (обычно) таким же, как размер массива.

  • 0
    В чем разница между последним индексом и размером массива? Индекс не является последовательным от 0 до размера массива?
  • 29
    Размер (1,2,3) равен 3, а индексы (по умолчанию) 0, 1 и 2. Таким образом, $ # arr будет 2 в этом случае, а не 3.
Показать ещё 6 комментариев
33

Во-первых, вторая не эквивалентна двум другим. $#array возвращает последний индекс массива, который меньше размера массива.

Остальные два практически одинаковы. Вы просто используете два разных способа создания скалярного контекста. Это сводится к вопросу удобочитаемости.

Я лично предпочитаю следующее:

say 0+@array;          # Represent @array as a number

Я нахожу это более ясным, чем

say scalar(@array);    # Represent @array as a scalar

и

my $size = @array;
say $size;

Последний выглядит совершенно ясно, как это, но я считаю, что дополнительная линия отбирает ясность в части другого кода. Это полезно для обучения тому, что @array делает в скалярном контексте, и, возможно, если вы хотите использовать $size более одного раза.

  • 15
    Лично я предпочитаю версию, которая использует ключевое слово «scalar», потому что совершенно очевидно, что оно форсирует скалярный контекст. my $size=@array выглядит так, как будто ошибочно использовался сигил.
  • 5
    Это действительно плохая идея. Люди, которые используют scalar без причины, учатся на неправильном уроке. Они начинают думать, что операторы возвращают списки, которые можно привести в скаляры. Видел это десятки раз.
Показать ещё 11 комментариев
26

Это получает размер, заставляя массив в скалярном контексте, в котором он оценивается как его размер:

print scalar @arr;

Это еще один способ принудительного преобразования массива в скалярный контекст, поскольку он присваивается скалярной переменной:

my $arrSize = @arr;

Это получает индекс последнего элемента в массиве, поэтому на самом деле размер минус 1 (при условии, что индексы начинаются с 0, что настраивается в Perl, хотя это обычно плохо):

print $#arr;

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

my $lastElement = $arr[$#arr];

Кроме того, как вы можете видеть здесь, в Stack Overflow, эта конструкция не обрабатывается корректно большинством синтаксических маркеров...

  • 2
    Примечание: просто используйте $arr[-1] чтобы получить последний элемент. И $arr[-2] чтобы получить предпоследний, и так далее.
  • 1
    @tuomassalo: Я согласен, что ваше предложение - лучший подход. Оглядываясь назад, $#arr не очень полезная функция, и не случайно, что в других языках ее нет.
5

Все три дают тот же результат, если мы немного изменим второй:

my @arr = (2, 4, 8, 10);

print "First result:\n";
print scalar @arr; 

print "\n\nSecond result:\n";
print $#arr + 1; # Shift numeration with +1 as it shows last index that starts with 0.

print "\n\nThird result:\n";
my $arrSize = @arr;
print $arrSize;
  • 5
    Это чем-то отличается от того, что уже упоминалось в этом и этом ответе?
5

Чтобы использовать второй способ, добавьте 1:

print $#arr + 1; # Second way to print array size
  • 0
    for [0..$#array] { print $array[$_ ] } работает очень хорошо, хотя, если целью получения количества элементов является перебор массива. Преимущество в том, что вы получаете элемент, а также счетчик, которые выровнены.
5

Пример:

my @a = (undef, undef);
my $size = @a;

warn "Size: " . $#a;   # Size: 1. It not the size
warn "Size: " . $size; # Size: 2
2

Из perldoc perldata, который следует с уверенностью сказать:

Всегда верно следующее:

scalar(@whatever) == $#whatever + 1;

Просто до тех пор, пока вы не $# ничем и не загадочно увеличиваете размер или ваш массив.

Индексы массива начинаются с 0.

и

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

    @whatever = ();
    $#whatever = -1;

Что приводит меня к тому, что я искал, а именно, как определить массив пустым. Я нашел его, если $# empty == -1;

2

Типы переменных Perl документация perlintro содержит

Специальная переменная $#array сообщает вам индекс последнего элемента массива:

print $mixed[$#mixed];       # last element, prints 1.23

У вас может возникнуть соблазн использовать $#array + 1, чтобы рассказать вам, сколько элементов есть в массиве. Не беспокойтесь. Как это бывает, использование @array, где Perl ожидает найти скалярное значение ( "в скалярном контексте" ), даст вам количество элементов в массиве:

if (@animals < 5) { ... }

Документация perldata также охватывает это в разделе "Scalar values" .

Если вы оцениваете массив в скалярном контексте, он возвращает длину массива. (Обратите внимание, что это неверно для списков, которые возвращают последнее значение, например, C-запятой или встроенные функции, которые возвращают все, что они хотят возвращать.) Всегда верно следующее:

scalar(@whatever) == $#whatever + 1;

Некоторые программисты предпочитают использовать явное преобразование, чтобы не оставлять никаких сомнений:

$element_count = scalar(@whatever);

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

Длина массива - это скалярное значение. Вы можете найти длину массива @days, оценив $#days, как в csh. Однако это не длина массива; его индекс последнего элемента, который является другим значением, поскольку обычно существует 0-й элемент.

1

Существуют различные способы печати размера массива. Вот значения всех: Допустим, наш массив my @arr = (3,4);

Способ 1: скаляр

Это правильный способ получить размер массивов.

print scalar @arr;  # prints size, here 2

Метод 2: индексный номер

$#arr дает последний индекс массива. поэтому, если массив имеет размер 10, то его последним индексом будет 9.

print $#arr;     # prints 1, as last index is 1
print $#arr + 1; # Add 1 to last index to get array size

Мы добавляем 1, рассматривая массив как 0-indexed. Но, если на нем не лежит ноль, , эта логика завершится неудачно.

perl -le 'local $[ = 4; my @arr=(3,4); print $#arr + 1;'   # prints 6

Вышеприведенный пример печатает 6, потому что мы установили его начальный индекс на 4. Теперь индекс будет 5 и 6 с элементами 3 и 4 соответственно.

Способ 3:

Когда массив используется в скалярном контексте, он возвращает размер массива

my $size = @arr;
print $size;   # prints size, here 2

На самом деле метод 3 и метод 1 одинаковы.

0

Чтобы найти размер массива, используйте ключевое слово scalar:

print scalar @array;

Чтобы узнать последний индекс массива, существует $# (переменная по умолчанию Perl). Он дает последний индекс массива. Когда массив начинается с 0, мы получаем размер массива, добавляя его к $#:

print "$#array+1";

Пример:

my @a = qw(1 3 5);
print scalar @a, "\n";
print $#a+1, "\n";

Вывод:

3

3

Ещё вопросы

Сообщество Overcoder
Наверх
Меню