in reply to Searching a multidimensional list

BrowserUk has a good point. You need to clarify your requirements. However, assuming you mean "as ordered in the file", the following code should do:

#!/usr/bin/perl use warnings; use strict; my %Invoices; my $last_name = ''; my %data; while(my $line = <DATA>) { chomp $line; # Split the fields into a hash. Depending on your # data, this might be better done with Text::xSV. @data{qw(orig inv name date time)} = ($line, split(/\s+/, $line)); next unless $data{name} eq 'Robb' or $data{name} eq 'Larry'; next if $last_name eq $data{name}; # If this field passes the tests, save a *copy* for later use. push @{$Invoices{$data{name}}}, {%data}; } continue { # Store the last name seen $last_name = $data{name}; } # For each (Larry Robb) foreach (keys %Invoices) { # Sort the invoices by date then time, in reverse order. $Invoices{$_} = [sort { $b->{date} cmp $a->{date} or $b->{time} <=> $a->{time} } @{$Invoices{$_}}]; # Print out the most recent invoice. print "Most recent for $_: $Invoices{$_}[0]{orig}\n"; } __DATA__ 1056128833340 Robb 2003-06-20 665 ** 1056128833340 t028348 2003-06-20 607 1055439973653 T012697 2003-07-22 962 1055439973653 t012697 2003-07-22 948 1055439973653 t806174 2003-07-15 792 1055439973653 T806174 2003-07-15 791 1055439973653 t021191 2003-07-08 786 1055439973653 Robb 2003-06-17 503 1055439973653 Larry 2003-06-16 815 ** 1055439973653 t021191 2003-06-12 646

If you mean "most recent" and "immediately previous" as in timestamp, you will need to read the whole file in at once, sort on the timestamp (move the sort in the code above out to work on the entire file; maybe un-reverse the sort-order as well), and then process as shown above.

bbfu
Black flowers blossom
Fearless on my breath

Replies are listed 'Best First'.
Re: Re: Searching a multidimensional list
by Mister_Inkster (Initiate) on Aug 02, 2003 at 02:10 UTC
    Thanks BBFU!
    I implemented your code and it gives the most recent records for Larry and Robb, but I'm afraid I haven't been clear enough. I need to find within each set of records that share a common invoice number,
    1) the most recent record (by timestamp) where the AGENT is either Robb or Larry; AND
    2) the record (with the same invoice number) that immediately preceded it in the invoice chronology does NOT have Robb or Larry as the AGENT.
    The data will support these conditions.
    I hope that is clearer.
    MrI

      Ok, the following assumes that the file is already sorted by invoice number and then timestamp.

      #!/usr/bin/perl use warnings; use strict; #our $Logfile = 'file.log'; #open my $fh, $Logfile or die "Can't open $Logfile: $!\n"; my $fh = \*DATA; # Testing purposes # The first element of @records is the "current" line. # The second element is the "next" line, if any. my @records = get_next_record($fh); do { # Read the next line push @records, get_next_record($fh); if( ($records[0]{name} eq 'Larry' or $records[0]{name} eq 'Robb') and not ( # No more lines $#records and # Not the name ($records[1]{name} eq 'Larry' or $records[1]{name} eq 'Robb') ) ) { print $records[0]{record}; # Skip to the next set of records, and start over. # ('skip' is removed immediately and is only for place-holding.) @records = ('skip', find_next_record_set($fh, $records[0]{inv})); } # Remove the old "current" line, and make the next line current. shift @records; } while @records; exit; sub parse_record { my $record = shift; my %data = ('record' => $record); @data{qw(inv name date time)} = split(/\s+/, $record); return \%data; } sub get_next_record { my $fh = shift; my $rec = <$fh>; return defined($rec) ? parse_record($rec) : (); } sub find_next_record_set { my $fh = shift; my $rs = shift; my $line; 1 while(defined($line = <$fh>) and $line =~ /^\Q$rs/); return defined($line) ? parse_record($line) : (); } __DATA__ 1056128833340 Robb 2003-06-20 665 ** 1056128833340 t028348 2003-06-20 607 1055439973653 T012697 2003-07-22 962 1055439973653 t012697 2003-07-22 948 1055439973653 t806174 2003-07-15 792 1055439973653 T806174 2003-07-15 791 1055439973653 t021191 2003-07-08 786 1055439973653 Robb 2003-06-17 503 1055439973653 Larry 2003-06-16 815 ** 1055439973653 t021191 2003-06-12 646

      bbfu
      Black flowers blossom
      Fearless on my breath

        Thank you BBFU. It works beautifully. Now I'll try to figure out HOW it works! Thanks again.
        MrI