La siguiente versión realiza lo que quieres, usando una subrutina.
Using perl Syntax Highlighting
#!/usr/bin/perl
use v5.14;
use strict;
use warnings;
my @array1 = ( "Fred Flinstone", "Wilma Flinstone", "Barney Rubble", "Betty Rubble" );
my @list = ( "Ba", "Wil" );
my $extract_ref = busca(\@array1, \@list);
for (@$extract_ref) {
say;
}
sub busca {
my ($lista1_ref, $lista2_ref) = @_;
my @extract;
for my $unit (@$lista2_ref) {
push @extract, grep /$unit/, @$lista1_ref;
}
return \@extract;
}
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
Como dices que quieres aplicarlo a Bioinformática, damos por supuesto que las cadenas a comparar pueden ser muy grandes. O quizás no. Vamos a suponer que sí. En ese caso, nos interesa que el programa no "mueva" esas cadenas entre la parte principal del programa y la subrutina. Usaremos la misma técnica que en otros lenguajes: en lugar de que los argumentos se pasen por valor, pasaremos una referencia a ese valor. Esto es algo muy rápido. No importa que la cadena de texto ocupe varios gigas. Solo pasamos una referencia, que ocupa muy poco.
En este caso concreto, a la subrutina le pasaremos una referencia a los dos arrays. De esa manera, no importa que los arrays tenga cuatro elementos o cuatro millones.
El paso de referencias como argumentos obliga a que accedamos a los elementos del array, desreferenciando. Por eso ves en el código los caracteres '@$' delante de los nombres de las variables.
El resultado es un array, pero en lugar de devolverlo tal cual, devolvemos una referencia. En la parte principal del programa lo recibimos y accedemos a los elementos de la misma manera que en la subrutina.
Con esto conseguimos una buena velocidad, pero se puede conseguir mucha más velocidad.
Dentro de la subrutina, estamos haciendo un bucle por todos los elementos de lista2. Por cada elemento de estos, lo comparamos con todos los elementos de lista1. Eso puede tardar mucho, si las listas son grandes (o con elementos muy grandes).
Una opción es la de convertir todos los elementos de lista2 en una única expresión regular:
Using perl Syntax Highlighting
#!/usr/bin/perl
use v5.14;
use strict;
use warnings;
my @array1 = ( "Fred Flinstone", "Wilma Flinstone", "Barney Rubble", "Betty Rubble" );
my @list = ( "Ba", "Wil" );
my $extract_ref = busca(\@array1, \@list);
say for @$extract_ref;
sub busca {
my ($lista1_ref, $lista2_ref) = @_;
my $patron = join '|', @$lista2_ref; # creación del patrón como un grupo de opciones: A | B | C
my @extract = grep /$patron/, @$lista1_ref; # filtramos todos los datos con el patrón
return \@extract;
}
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
La ventaja, además, es que el resultado contiene los elementos coincidentes en el mismo orden que están en lista1.
Edito: Esta versión usa la nueva sintaxis de desreferencia, y es un pelín más rápida.
Using perl Syntax Highlighting
#!/usr/bin/perl
use v5.20;
use strict;
use warnings;
my @array1 = ( "Fred Flinstone", "Wilma Flinstone", "Barney Rubble", "Betty Rubble" );
my @list = ( "Ba", "Wil" );
my $extract_ref = busca(\@array1, \@list);
say for $extract_ref->@*;
sub busca {
my ($lista1_ref, $lista2_ref) = @_;
my $patron = join '|', $lista2_ref->@*;
return [ grep /$patron/, $lista1_ref->@* ];
}
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4