web-dev-qa-db-fra.com

Perl: Un bon moyen de tester si une valeur est dans un tableau?

Si j'ai un tableau:

@int_array = (7,101,80,22,42);

Comment puis-je vérifier si la valeur entière 80 est dans le tableau sans parcourir tous les éléments?

14
coding4fun

Vous ne pouvez pas sans boucler. Cela fait partie de ce que signifie être un tableau. Vous pouvez utiliser une boucle implicite en utilisant grep ou smartmatch, mais il y a toujours une boucle. Si vous voulez éviter la boucle, utilisez un hash à la place (ou en plus).

# grep
if ( grep $_ == 80, @int_array ) ...

# smartmatch
use 5.010001;
if ( 80 ~~ @int_array ) ...

Avant d'utiliser smartmatch, notez:

http://search.cpan.org/dist/Perl-5.18.0/pod/perldelta.pod#The_smartmatch_family_of_features_are_now_experimental :

La famille de fonctionnalités smartmatch est maintenant expérimentale

La correspondance intelligente, ajoutée dans la version 5.10.0 et modifiée de manière significative dans la version 5.10.1, fait régulièrement l'objet de plaintes. Bien qu’elle soit utile de plusieurs manières, elle s’est également révélée problématique et source de confusion pour les utilisateurs et les développeurs de Perl. Un certain nombre de propositions ont été formulées sur la meilleure façon de résoudre le problème. Il est clair que le smartmatch va presque certainement changer ou disparaître dans le futur. S'appuyer sur son comportement actuel n'est pas recommandé.

Des avertissements seront désormais émis lorsque l'analyseur verra ~~, donné ou quand. Pour désactiver ces avertissements, vous pouvez ajouter cette ligne à la portée appropriée.

31
ysth

Solution CPAN: utilisez List::MoreUtils

use List::MoreUtils qw{any}; 
print "found!\n" if any { $_ == 7 } (7,101,80,22,42);

Si vous devez effectuer BEAUCOUP DE recherches dans le même tableau, une méthode plus efficace consiste à stocker le tableau dans un hachage une fois et à le rechercher dans le hachage:

@int_array{@int_array} = 1;
foreach my $lookup_value (@lookup_values) {
    print "found $lookup_value\n" if exists $int_array{$lookup_value}
}

Pourquoi utiliser cette solution sur les alternatives?

  • Impossible d'utiliser la correspondance intelligente dans Perl avant la 5.10. Selon ce SO message de brian d foy] 2 , la correspondance intelligente est un court-circuit, elle vaut donc "n'importe quelle" solution pour 5.10.

  • La solution grep parcourt la liste entière même si le premier élément de 1 000 000 longues correspond. any court-circuitera et quittera le moment où le premier match est trouvé, donc c'est plus efficace. Affiche originale explicite "sans passer par tous les éléments"

  • Si vous devez effectuer BEAUCOUP de recherches, le coût unique irrécupérable de la création de hachage rend la méthode de recherche de hachage BEAUCOUP plus efficace que toute autre. Voir this SO post pour plus de détails

7
DVK

Encore un autre moyen de rechercher un nombre dans un tableau:

#!/usr/bin/env Perl

use strict;
use warnings;

use List::Util 'first';

my @int_array       = qw( 7 101 80 22 42 );
my $number_to_check = 80;

if ( first { $_ == $number_to_check } @int_array ) {
    print "$number_to_check exists in ", join ', ', @int_array;
}

Voir List::Util .

3
Alan Haggai Alavi
if ( grep /^80$/, @int_array ) {
    ...
}
0
Matteo Riva

Si vous utilisez Perl 5.10 ou une version ultérieure, vous pouvez utiliser le correspondance intelligente opérateur ~~:

my $found = (80 ~~ $in_array);
0
aschepler