2009-06-01 5 views
5

I haben eine Funktion, die extrahiert Excel Daten in ein Array von Hashes etwa so:Suche nach hash in einem Array von Wert

 

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

das Array von Hashes Bestücken fein ist. Der schwierige Teil ist jedoch die Suche nach einem bestimmten Element (Hash) im Array. Ich kann nicht scheinen, um Artikel zu finden, die eine ID oder 21, oder eine Charge von 15, oder eine Kosten> $ 20 etc. haben können.

Wie würde ich über die Einrichtung einer solchen Sucheinrichtung gehen?

Vielen Dank an alle,

+0

Sie könnten einfach einen anonymen Hash Ref Push (@array, {id => $ id}); –

+0

Während Sie nicht direkt auf Ihre Frage bezogen sind, sollten Sie Text :: xSV zum Analysieren der CSV-Datei betrachten. Nur ein Split auf "," ist nicht 100% zuverlässig für das Parsen. Es gibt auch ein Spreadsheet :: ParseExcel-Modul, das Excel-Binärdateien parsen kann. – jiggy

Antwort

18

Mit der Kraft der grep

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

Wenn Sie wissen, wird es nur ein Element zurückgegeben werden Sie dies nur tun können:

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

(Ungeprüfte, und ich habe nicht eine von diesen in einer Weile geschrieben, aber das sollte funktionieren)

+0

Danke für deine Einsicht David. In Bezug auf Ihre Lösung gibt dies eine Reihe von Ergebnissen zurück, während, weil es wirklich nur ein Vorkommen gibt, sollte ein Hash und kein Array zurückgegeben werden. Wäre diese Lösung weiterhin gültig, wenn anstelle eines Arrays von Hashwerten ein Hash zurückgegeben wird? –

+1

Wenn Sie sicher sind, dass nur ein Wert zurückgegeben wird, können Sie $ matching_items [0] verwenden oder my $ matching_items = (grep { $ _-> {id} == 21 } @array_data_or) [0 ]; –

+0

@DidYouJustDoThat: Angenommen, es gibt nur eine Übereinstimmung ist nicht unbedingt sicher. Einige Ihrer Beispiele (z. B. Kosten> 20) können mehrere Elemente zurückgeben. –

5

Wenn Sie sicher sind, dass die Suche immer nur ein Vorkommen zurückgibt oder wenn Sie in nur das erste Spiel interessiert sind, dann könnte man den ‚ersten‘ Unterprogramm in List::Util

use List::Util; 

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

ich das Unterprogramm-Aufruf verwenden Sie eingeschlossen in Der % {} Block, um sicherzustellen, dass der RHS zu einem Hash ausgewertet wird.

+0

Die% {} um den Aufruf von first() dereferenziert die Hashref aus dem Array und erstellt eine (seichte) Kopie. Je nachdem, wie das OP es verwendet, kann das ein Problem sein. Ich würde stattdessen den hashref zurückgeben: '$ hr = first {$ _-> {id} == 21} @ array_data_or' –

+0

Ich würde es auch vorziehen, zurückzukehren und später den hashref zu verwenden, aber laut DidYouJustDoThats Kommentar zu David Dowards Antwort, Das Poster sucht nach einem Hash und nicht nach einer Referenz. – aks

+0

Ich denke, "Hash" ist nur schlampig Terminologie. Er möchte einen einzelnen Wert anstelle einer Liste. –

Verwandte Themen