Подсчет элементов массива в Perl - PullRequest
27 голосов
/ 14 мая 2009

Как получить общее количество элементов в массиве, а НЕ последний идентификатор?

Ни один из двух способов, которые я нашел, чтобы сделать это работает:

my @a;
# Add some elements (no consecutive ids)
$a[0]= '1';
$a[5]= '2';
$a[23]= '3';

print $#a, "\n"; # Prints 23
print scalar(@a), "\n"; # Prints 24

Я ожидал получить 3 ...

Ответы [ 6 ]

39 голосов
/ 14 мая 2009

Редактировать: хэш против массива

Как правильно указал cincodenada в комментарии, ysth дал лучший ответ: я должен был ответить на ваш вопрос другим вопросом: «Вы действительно хотите использовать массив Perl?

Массив выделяет память для всех возможных индексов вплоть до самого большого используемого до сих пор. В вашем примере вы выделяете 24 ячейки (но используете только 3). Напротив, хеш выделяет пространство только для тех полей, которые фактически используются.

Массив: скалярная grep

Вот два возможных решения (см. Объяснение ниже):

print scalar(grep {defined $_} @a), "\n";  # prints 3
print scalar(grep $_, @a), "\n";            # prints 3

Объяснение: После добавления $a[23] ваш массив действительно содержит 24 элемента - но большинство из них не определены (что также оценивается как ложное). Вы можете подсчитать количество определенных элементов (как в первом решении) или количество истинных элементов (второе решение).

В чем разница? Если вы установите $a[10]=0, то первое решение будет считать его, но второе решение не будет (потому что 0 ложно, но определено). Если вы установите $a[3]=undef, ни одно из решений не будет учитываться.

Хеш-решение (по yst)

Как предлагает другое решение, вы можете работать с хешем и избежать всех проблем:

$a{0}  = 1;
$a{5}  = 2;
$a{23} = 3;
print scalar(keys %a), "\n";  # prints 3

Это решение подсчитывает нули и неопределенные значения.

16 голосов
/ 14 мая 2009

Звучит так, как будто вы хотите разреженный массив . В обычном массиве было бы 24 элемента, а в разреженном массиве - 3. В Perl мы эмулируем разреженные массивы хешами:

#!/usr/bin/perl

use strict;
use warnings;

my %sparse;

@sparse{0, 5, 23} = (1 .. 3);

print "there are ", scalar keys %sparse, " items in the sparse array\n",
    map { "\t$sparse{$_}\n" } sort { $a <=> $b } keys %sparse;

Функция keys в скалярном контексте возвращает количество элементов в разреженном массиве. Единственным недостатком использования хэша для эмуляции разреженного массива является то, что вы должны отсортировать ключи перед их повторением, если важен их порядок.

Вы также должны не забыть использовать функцию delete для удаления элементов из разреженного массива (недостаточно просто установить их значение undef).

14 голосов
/ 14 мая 2009

Может быть, вы хотите вместо этого хеш (или дополнительно). Массивы - это упорядоченный набор элементов; если вы создаете $foo[23], вы неявно создаете $foo[0] до $foo[22].

8 голосов
/ 14 мая 2009

распечатать скалярный grep {определенный $ _} @a;

2 голосов
/ 28 декабря 2013
@people = qw( bob john linda ); 
$n = @people; # the number 3
Print " le number in the list is $n \n"; 

выражения в Perl всегда вернуть соответствующее значение для их контекста. Например, как насчет «имени» * массив. В контексте списка он дает список элементов. Но в скалярном контексте он возвращает количество элементов в массиве:

0 голосов
/ 19 марта 2012
sub uniq {
    return keys %{{ map { $_ => 1 } @_ }};
}
my @my_array = ("a","a","b","b","c");
#print join(" ", @my_array), "\n";
my $a = join(" ", uniq(@my_array));
my @b = split(/ /,$a);
my $count = $#b;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...