(parti di questa risposta sono un contributo di Anno Siegel)
Già sentire la parola "in" è un'indicazione che avreste
probabilmente dovuto utilizzare un hash, non una lista o un array, per
memorizzare i vostri dati. Gli hash sono progettati per offrire una risposta
rapida ed efficiente a questa domanda. Gli array no.
Detto questo, ci sono molti modi per risolvere la questione. Se dovete fare
questa operazione molte volte su stringhe arbitrarie, la via più
veloce è probabilmente quella di invertire l'array originale e
creare un hash le cui chiavi sono gli elementi dell'array.
@blu = qw/azzurro ceruleo celeste turchese oltremare/;
%un_blu = ();
for (@blu) { $un_blu{$_} = 1 }
Ora potete controllare se è $un_blu{$un_colore}. Potrebbe essere stata una
buona idea quella di memorizzare i blu in un hash sin dall'inizio.
Se i valori sono tutti interi piccoli, potete usare un semplice array
indicizzato. Questo tipo di array utilizzerà meno spazio:
@primi = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
@un_piccolo_primo = ();
for (@primi) { $un_piccolo_primo[$_] = 1 }
# o semplicemente @un_piccolo_primo[@primi] = (1) x @primi;
Ora potete controllare se è $un_piccolo_primo[$un_numero].
Se i valori in questione sono interi anziché stringhe, potete
salvare molto spazio utilizzando le stringhe di bit:
@articoli = ( 1..10, 150..2000, 2017 );
undef $letti;
for (@articoli) { vec($letti,$_,1) = 1 }
Ora controllate se vec($letti,$n,1) è vero per un determinato $n.
Questi metodi garantiscono che i test individuali siano eseguiti rapidamente ma
richiedono una riorganizzazione dell'originale lista o array. Sono redditizzi solo se
dovete testare valori multipli sullo stesso array.
Se ne state testando solo uno, il modulo standard List::Util esporta, a questo scopo,
la funzione first. Funziona fermandosi una volta che ha trovato l'elemento.
È scritta in C per la velocità ed il suo equivalente in Perl
assomiglia a questa subroutine:
sub first (&@) {
my $codice = shift;
foreach (@_) {
return $_ if &{$codice}();
}
undef;
}
Se la velocità è una cosa di poco interesse, lo stile più diffuso
è quello di utilizzare grep in contesto scalare (che restituisce il numero di elementi
che hanno verificato la sua condizione) per traversare l'intera lista. Tuttavia, questo ha il
sicuro vantaggio di rivelarvi quante corrispondenze ha trovato.
my $presente = grep $_ eq $qualsiasicosa, @array;
Se in realtà volete estrarre gli elementi che effettuano il match, usate semplicemente
grep in contesto di lista.
my @match = grep $_ eq $qualsiasicosa, @array;
|