2009-06-01 9 views
5

que tiene una función que extrae datos de Excel en un conjunto de valores hash de este modo:Búsqueda de hachís en una matriz por valor

 

sub set_exceldata { 

    my $excel_file_or = '.\Excel\ORDERS.csv'; 
    if (-e $excel_file_or) { 

     open (EXCEL_OR, $excel_file_or) || die("\n can't open $excel_file_or: $!\n");     
     while() { 

      chomp; 
      my ($id, $date, $product, $batchid, $address, $cost) = split ","; 
      my %a = (id  => $id 
        , date => $date 
        , product => $product 
        , batchid => $batchid 
        , address => $address 
        , cost => $cost 
        ); 
      push (@array_data_or, \%a); 
     } 
     close EXCEL_OR; 
    } 
} 

Llenar la matriz de valores hash está muy bien. Sin embargo, la parte difícil es buscar un elemento en particular (hash) en la matriz. Parece que no puedo encontrar elementos que puedan tener una identificación o 21, o un lote de 15, o un costo> $ 20, etc.

¿Cómo podría implementar esta herramienta de búsqueda?

Gracias a todos,

+0

Podrías simplemente presionar un push hash anónimo (@array, {id => $ id}); –

+0

Si bien no está directamente relacionado con su pregunta, debe consultar Text :: xSV para analizar el archivo .csv. Solo hacer una división en "," no es 100% confiable para analizar. También hay un módulo Spreadsheet :: ParseExcel que puede analizar binarios de Excel. – jiggy

Respuesta

18

Con el poder de grep

my @matching_items = grep { 
    $_->{id} == 21 
} @array_data_or; 

Si sabe que habrá un solo artículo devuelto sólo se puede hacer esto:

my ($item) = grep { 
    $_->{id} == 21 
} @array_data_or; 

(no probado, y no he escrito uno de estos en un tiempo, pero esto debería funcionar)

+0

Gracias por su visión David. En cuanto a su solución, esto arroja una matriz de resultados, mientras que porque realmente solo habrá una ocurrencia, se debe devolver un hash y no una matriz. ¿Sería esta solución aún válida al devolver un hash en lugar de una matriz de hashes? –

+1

si está seguro de que van a devolver un valor que se puede usar $ matching_items [0], o hacer mis $ matching_items = (grep { $ _-> {id} == 21 } @array_data_or) [0 ]; –

+0

@DidYouJustDoThat: Suponer que solo hay una coincidencia no es necesariamente seguro. Algunos de sus ejemplos (por ejemplo, costo> 20) pueden devolver varios elementos. –

5

Si está seguro de que la búsqueda siempre devuelve una sola ocurrencia o si usted está interesado sólo en el primer partido, entonces podría utilizar el 'primero' subrutina que se encuentra en List::Util

use List::Util; 

my %matching_hash = %{ first { $_->{id} == 21 } @array_data_or }; 

I delimitada la llamada a una subrutina en el bloque % {} para asegurarse de que el RHS se evalúa como un hash.

+0

El% {} alrededor de la llamada a first() desreferencia el hashref de la matriz, haciendo una copia (superficial). Eso podría ser un problema dependiendo de cómo lo use el OP. Devolvería el hashref en su lugar: '$ hr = first {$ _-> {id} == 21} @ array_data_or' –

+0

Yo también preferiría regresar y luego usar el hashref, pero de acuerdo con DidYouJustDo. Es un comentario a la respuesta de David Doward, el poster está buscando un hash y no una referencia. – aks

+0

Creo que decir "hash" es una terminología descuidada. Él quiere un valor único en lugar de una lista. –

Cuestiones relacionadas