web-dev-qa-db-fra.com

Compter les éléments du tableau en Perl

Comment obtenir le nombre total d'éléments dans un tableau, PAS le dernier identifiant?

Aucun des deux moyens que j'ai trouvés pour faire cela fonctionne:

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

Je m'attendais à en avoir 3 ...

27
grilix

Edit: Hash versus Array

Comme cincodenada l'a correctement souligné dans le commentaire, ysth a donné une meilleure réponse: j'aurais dû répondre à votre question par une autre question: "Voulez-vous vraiment utiliser un tableau Perl? Un hachage peut être plus approprié."

Un tableau alloue de la mémoire pour tous les indices possibles jusqu'au plus grand utilisé jusqu'à présent. Dans votre exemple, vous allouez 24 cellules (mais n'en utilisez que 3). En revanche, un hachage alloue uniquement de l'espace pour les champs qui sont réellement utilisés.

Solution de tableau: grep scalaire

Voici deux solutions possibles (voir ci-dessous pour l'explication):

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

Explication: après avoir ajouté $a[23], votre tableau contient vraiment 24 éléments --- mais la plupart d'entre eux ne sont pas définis (ce qui est également évalué comme faux). Vous pouvez compter le nombre d'éléments définis (comme dans la première solution) ou le nombre d'éléments vrais (seconde solution).

Quelle est la différence? Si vous définissez $a[10]=0, alors la première solution le comptera, mais pas la seconde (car 0 est faux mais défini). Si vous définissez $a[3]=undef, aucune des solutions ne le comptera.

Solution de hachage (par yst)

Comme suggéré par une autre solution, vous pouvez travailler avec un hachage et éviter tous les problèmes:

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

Cette solution compte les zéros et les valeurs non définies.

39
Yaakov Belch

Il semble que vous souhaitiez un tableau clairsemé . Un tableau normal contiendrait 24 éléments, mais un tableau clairsemé en aurait 3. En Perl, nous émulons des tableaux clairsemés avec des hachages:

#!/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;

La fonction keys dans un contexte scalaire renverra le nombre d'éléments dans le tableau fragmenté. Le seul inconvénient de l'utilisation d'un hachage pour émuler un tableau fragmenté est que vous devez trier les clés avant de les répéter si leur ordre est important.

Vous devez également vous rappeler d'utiliser la fonction delete pour supprimer des éléments du tableau épars (il ne suffit pas de définir leur valeur sur undef).

16
Chas. Owens

Vous souhaitez peut-être un hachage à la place (ou en plus). Les tableaux sont un ensemble ordonné d'éléments; si vous créez $foo[23], vous créez implicitement $foo[0] par $foo[22].

14
ysth

print grep scalaire {defini $ _} @a;

8
kcwu
@people = qw( bob john linda ); 
$n = @people; # the number 3
Print " le number in the list is $n \n"; 

Les expressions en Perl renvoient toujours la valeur appropriée à leur contexte. Par exemple, que diriez-vous du "nom" * d'un tableau. Dans un contexte de liste, il donne la liste des éléments. Mais dans un contexte scalaire, il renvoie le nombre d'éléments dans le tableau:

2
Zhugo
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;
0
santosh