2010-12-31 16 views
11

Si tengo una matriz:Perl: ¿una buena forma de comprobar si un valor se encuentra en una matriz?

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

¿Cómo puedo comprobar si el valor entero 80 se encuentra en la matriz sin bucle a través de cada elemento?

+0

Parece un duplicado: http://stackoverflow.com/questions/2860226 – Calimo

+0

Posible duplicado de [¿Cómo puedo comprobar si una matriz Perl contiene un valor particular?] (Http://stackoverflow.com/questions/2860226/how-can-i-check-if-a-perl-array-contains-a-particular-value) – ThisSuitIsBlackNot

Respuesta

29

No se puede hacer sin bucles. Eso es parte de lo que significa ser una matriz. Puede usar un bucle implícito usando grep o smartmatch, pero todavía hay un bucle. Si desea evitar el bucle, use un hash en su lugar (o además).

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

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

Antes de utilizar SmartMatch, tenga en cuenta:

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

La familia SmartMatch de características ahora son experimentales

partido inteligente, añade en v5.10.0 y revisado significativamente en v5.10.1, ha sido un punto de queja regular. Aunque hay varias maneras en que es útil, también ha resultado problemático y confuso tanto para los usuarios como para los implementadores de Perl. Ha habido una serie de propuestas sobre cómo abordar mejor el problema. Está claro que Smartmatch casi seguro va a cambiar o desaparecerá en el futuro. No se recomienda confiar en su comportamiento actual.

Las advertencias ahora se emitirán cuando el analizador vea ~~, o cuando. Para desactivar estas advertencias, puede agregar esta línea al alcance apropiado

+0

++. Smart Match (o tal vez algo de List :: MoreUtils) es el camino a seguir. Para completar, así es cómo podría hacerlo con un hash: mi @array = 1..1000; mi% hash; undef @hash {@array}; di "¡10 está en la matriz!" si existe $ hash {10}; – Hugmeir

+2

'undef @hash {@array}' funciona, pero en realidad no está documentado para hacerlo. use '@hash {@array} =()' en su lugar. – ysth

+0

No estaba seguro de lo que quería decir, así que busqué en Google y encontré esto: http://www.perlmonks.org/?node_id=435223 Gracias por la corrección, ¡ysth! – Hugmeir

0
if (grep /^80$/, @int_array) { 
    ... 
} 
+0

También coincide con 180 y 800. – aschepler

+0

Anclas añadidas .. –

+0

Usar grep en general para esto no es una buena idea ; asignará una lista extra para contener los resultados del grep, y seguirá funcionando a través de la matriz, incluso si el primer elemento es 80. –

0

Si está utilizando Perl 5.10 o posterior, puede utilizar el smart match operador ~~: solución

my $found = (80 ~~ $in_array); 
7

CPAN: utilizar List::MoreUtils

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

Si necesita hacer MANY MANY búsquedas en la misma matriz, una forma más eficiente es almacenar la matriz en una función hash una vez y buscar en el hash :

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

¿Por qué utilizar esta solución sobre las alternativas?

  • No se puede usar la coincidencia inteligente en Perl antes de la 5.10. De acuerdo con esta publicación de SO por brian d foy] 2, la coincidencia inteligente está en cortocircuito, por lo que es tan buena como "cualquier" solución para 5.10.

  • grep solución pasa por la lista completa incluso si el primer elemento de la lista larga de 1,000,000 coincide. any se cortocircuitará y saldrá en el momento en que se encuentre la primera coincidencia, por lo tanto es más eficiente. El cartel original decía explícitamente "sin pasar por todos los elementos"

  • Si necesita hacer MUCHOS de búsquedas, el costo hundido de creación de hash hace que el método de búsqueda de hash sea MUCHO más eficiente que cualquier otro.Ver this SO post for details

+0

Bueno, depende del tamaño de la matriz y del número de comprobaciones que necesita realizar. El análisis de un módulo externo puede ser menos eficiente que un 'grep' completo. –

+0

Además, si la eficiencia es la principal preocupación, simplemente haga un manual 'foreach' con' last'. –

+2

@kemp - IIRC, List :: MoreUtils tiene una implementación XS. Eso es más rápido que el foreach con el último. si usa Perl nativo, eso es probablemente lo que hace el módulo de todos modos. – DVK

3

Sin embargo, otra manera de comprobar si hay un número en una matriz:

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

Ver List::Util.

Cuestiones relacionadas