recorrer - splice perl español
¿Cómo puedo verificar que un valor esté presente en una matriz(lista) en Perl? (8)
Tengo una lista de valores posibles:
@a = qw(foo bar baz);
¿Cómo verifico de manera concisa que un valor $val
está presente o ausente en @a
?
Una implementación obvia es recorrer la lista, pero estoy seguro de que TMTOWTDI .
¡Gracias a todos los que respondieron! Las tres respuestas que me gustaría destacar son:
La respuesta aceptada: la forma más "integrada" y compatible con versiones anteriores.
La respuesta de RET es la más limpia, pero solo válida para Perl 5.10 y posteriores.
La respuesta de draegtun es (posiblemente) un poco más rápida, pero requiere el uso de un módulo adicional. No me gusta agregar dependencias si puedo evitarlas, y en este caso no necesito la diferencia de rendimiento, pero si tiene una lista de 1,000,000 de elementos, puede intentar probar esta respuesta.
Esto se responde en la respuesta de perlfaq4 a "¿Cómo puedo saber si un determinado elemento está contenido en una lista o matriz?" .
Para buscar en perlfaq, puede buscar a través de la lista de todas las preguntas en perlfaq usando su navegador favorito.
Desde la línea de comandos, puede usar el modificador -q a perldoc para buscar palabras clave. Habría encontrado tu respuesta buscando "lista":
perldoc -q list
(porciones de esta respuesta aportadas por Anno Siegel y Brian Foy)
Escuchar la palabra "in" es una indicación de que probablemente debiste haber usado un hash, no una lista o matriz, para almacenar tus datos. Los hashes están diseñados para responder a esta pregunta de manera rápida y eficiente. Las matrices no son
Dicho esto, hay varias formas de abordar esto. En Perl 5.10 y posterior, puede usar el operador de coincidencia inteligente para verificar que un elemento esté contenido en una matriz o un hash:
use 5.010;
if( $item ~~ @array )
{
say "The array contains $item"
}
if( $item ~~ %hash )
{
say "The hash contains $item"
}
Con las versiones anteriores de Perl, debe hacer un poco más de trabajo. Si va a hacer esta consulta muchas veces sobre valores de cadena arbitrarios, la forma más rápida es probablemente invertir la matriz original y mantener un hash cuyas claves sean los primeros valores de la matriz:
@blues = qw/azure cerulean teal turquoise lapis-lazuli/;
%is_blue = ();
for (@blues) { $is_blue{$_} = 1 }
Ahora puede verificar si $ is_blue {$ some_color}. Podría haber sido una buena idea mantener el blues todo en un hash en primer lugar.
Si los valores son enteros pequeños, podría usar una matriz indexada simple. Este tipo de matriz ocupará menos espacio:
@primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
@is_tiny_prime = ();
for (@primes) { $is_tiny_prime[$_] = 1 }
# or simply @istiny_prime[@primes] = (1) x @primes;
Ahora comprueba si $ is_tiny_prime [$ some_number].
Si los valores en cuestión son enteros en lugar de cadenas, puede ahorrar bastante espacio usando cadenas de bits:
@articles = ( 1..10, 150..2000, 2017 );
undef $read;
for (@articles) { vec($read,$_,1) = 1 }
Ahora comprueba si vec ($ read, $ n, 1) es verdadero para algunos $ n.
Estos métodos garantizan pruebas individuales rápidas pero requieren una reorganización de la lista o matriz original. Solo pagan si tiene que probar varios valores con la misma matriz.
Si está probando solo una vez, el módulo estándar List :: Util exporta la función primero para este propósito. Funciona deteniéndose una vez que encuentra el elemento. Está escrito en C para velocidad, y su equivalente Perl se parece a esta subrutina:
sub first (&@) {
my $code = shift;
foreach (@_) {
return $_ if &{$code}();
}
undef;
}
Si la velocidad es de poca importancia, la expresión común utiliza grep en contexto escalar (que devuelve el número de elementos que pasaron su condición) para recorrer toda la lista. Sin embargo, esto tiene el beneficio de decirle cuántas coincidencias encontró.
my $is_there = grep $_ eq $whatever, @array;
Si desea extraer realmente los elementos coincidentes, simplemente use grep en el contexto de la lista.
my @matches = grep $_ eq $whatever, @array;
La función bulit de Perl en grep () está diseñada para hacer esto.
@matches = grep( /^MyItem$/, @someArray );
o puedes insertar cualquier expresión en el matcher
@matches = grep( $_ == $val, @a );
Si no le gusta la dependencia innecesaria, implemente any
o first
usted mismo
sub first (&@) {
my $code = shift;
$code->() and return $_ foreach @_;
undef
}
sub any (&@) {
my $code = shift;
$code->() and return 1 foreach @_;
undef
}
Si tiene perl 5.10, use el operador de coincidencia inteligente ~~
print "Exist/n" if $var ~~ @array;
Es casi mágico.
Solución interesante, especialmente para búsquedas repetidas:
my %hash;
map { $hash{$_}++ } @a;
print $hash{$val};
Un posible enfoque es usar la función List :: MoreUtils ''any''.
use List::MoreUtils qw/any/;
my @array = qw(foo bar baz);
print "Exist/n" if any {($_ eq "foo")} @array;
Actualización : corregida según el comentario de zoul.
Utilice la primera función de List::Util que viene de serie con Perl ....
use List::Util qw/first/;
my @a = qw(foo bar baz);
if ( first { $_ eq ''bar'' } @a ) { say "Found bar!" }
NÓTESE BIEN. primero devuelve el primer elemento que encuentra y por lo tanto no tiene que iterar a través de la lista completa (que es lo que hará grep ).
$ perl -e ''@a = qw(foo bar baz);$val="bar";
if (grep{$_ eq $val} @a) {
print "found"
} else {
print "not found"
}''
encontró
$val=''baq'';
extraviado