2009-06-01 11 views
5

I ont une fonction qui extrait les données Excel dans un tableau de hash comme ceci:Rechercher hachage dans un tableau par valeur

 

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; 
    } 
} 

peuplant le tableau de hachages est très bien. Cependant, la partie difficile est la recherche d'un élément particulier (hachage) dans le tableau. Je n'arrive pas à localiser les articles qui pourraient avoir un ID ou 21, ou un batchid de 15, ou un coût> 20 $ etc.

Comment pourrais-je mettre en place un tel système de recherche?

Merci à tous,

+0

Vous pouvez simplement appuyer sur une commande de hachage anonyme (@array, {id => $ id}); –

+0

Bien que n'étant pas directement lié à votre question, vous devriez regarder Text :: xSV pour analyser le fichier .csv. Juste faire une scission sur "," n'est pas fiable à 100% pour l'analyse syntaxique. Il existe également un module Spreadsheet :: ParseExcel qui peut analyser les binaires Excel. – jiggy

Répondre

18

Avec la puissance de grep

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

Si vous savez qu'il y aura un seul article retourné, vous pouvez simplement faire ceci:

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

(non testé, et je n'en ai pas écrit depuis un moment, mais cela devrait fonctionner)

+0

Merci pour votre perspicacité David. En ce qui concerne votre solution, cela retourne un tableau de résultats alors que, parce qu'il n'y aura vraiment qu'une occurrence, devrait retourner un hachage et non un tableau. Cette solution serait-elle toujours valide lors du retour d'un hachage au lieu d'un tableau de hachages? –

+1

si vous êtes sûr qu'il retournera une seule valeur, vous pouvez utiliser $ matching_items [0], ou faire my $ matching_items = (grep { $ _-> {id} == 21 } @array_data_or) [0 ] –

+0

@DidYouJustDoThat: Supposer qu'il n'y a qu'une seule correspondance n'est pas nécessairement sans danger. Certains de vos exemples (par exemple, coût> 20) peuvent renvoyer plusieurs éléments. –

5

Si vous êtes sûr que la recherche retourne toujours une seule occurence ou si vous êtes intéressé que le premier match alors vous pouvez utiliser le sous-programme « première » trouvé dans List::Util

use List::Util; 

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

I ci-joint l'appel de sous-programme le bloc % {} pour s'assurer que le RHS évalue un hachage.

+0

Le% {} autour de l'appel à first() déréférence le hashref du tableau, en effectuant une copie (superficielle). Cela pourrait être un problème selon la façon dont le PO l'utilise. Je retournerais le hashref à la place: '$ hr = premier {$ _-> {id} == 21} @ array_data_or' –

+0

Moi aussi je préférerais revenir et utiliser plus tard le hashref mais selon le commentaire de DidYouJustDoThat à la réponse de David Doward, l'affiche cherche un hash et non une référence. – aks

+0

Je pense que dire "hash" est juste une terminologie bâclée. Il veut une seule valeur au lieu d'une liste. –