in reply to How to read data file into an array of hashes

Contrary to toolic's suggestion, I think you are right to try for an array of hashes, because you probably can't count on the "last name" field to be unique across all records.

So, to build on the otherwise fine code of the first reply:

use strict; use warnings; use Data::Dumper; my @clients; # make this an array, not a hash; my @fields = qw/surname firstname town/; while (<DATA>) { next if ( /^Surname/ or /^-/ ); my @values = unpack 'A13A16A20', $_; my %entry = map { $fields[$_] => $values[$_] } ( 0..$#fields ); push @clients, \%entry; } print Dumper(\@clients); __DATA__ Surname L20, First Name L20, Town L20 -------------------------------------------------- Chaplin Charlie Basel Estevez Emilio Santa Manica Sarte Jean Paul Montmarte Rikard Frank Amsterdam Rodin Paul Montmarte

(update: it does seem odd that the field widths in the column headings do not match the actual widths used in the data and in the unpack spec. It would be better if the headings were consistent with the data, but that's a minor point...)

Replies are listed 'Best First'.
Re^2: How to read data file into an array of hashes
by fseng (Novice) on Jun 24, 2009 at 04:43 UTC
    Thanks guys. But now I come up with one more question. Now I want to print all the lines sorted by the Town. Like this
    Town Surname Firstname Basel Chaplin Charlie Manica Estevez Emilio Santa Montmarte Sarte Jean Paul Montmarte Rodin Paul Amsterdam Rikard Frank
    I did something like this:
    my $data = "clients.dat"; open (DAT, $data) or die "\"$data\" not existed or can't be opened!\n" +; my @client; # make this an array, not a hash; my @fields = qw/surname firstname town/; while (<DAT>) { next if ( /^Surname/ or /^-/ ); my @values = unpack 'A20A20A20', $_; my %entry = map { $fields[$_] => $values[$_] } ( 0..$#fields ); push @client, \%entry; } my @towns; my $client; foreach my $client (@client){ push @towns, "$client->{'town'}"; } my @sorted_towns = sort @towns; foreach my $key (@sorted_towns) { my @elems = $key; my $client = $client->[$elems[1]-1]; print "$client->{'town'} $client->{'surname'} $client->{'firstname +'}"; }
    But this doesnt work somehow. Can anyone help please?
      You don't need (or want) to sort the town names into a separate array; after the AoH is loaded, you just need to loop over the list of sorted array elements, where the sorting is based on the "town" value, like this:
      for my $entry ( sort { $a->{town} cmp $b->{town} } @client ) { printf "%s\t%s\t%s\n", $entry->{town}, $entry->{surname}, $entry-> +{firstname}; }
      (not tested)

      (updated to add missing "->" in the printf statement, based on fseng's reply below)

        Thanks graff.I tested the code. It keeps giving error message: Global symbol "%entry" requires explicit package name. I try to declare it as my %entry, then it gives error message: use of unintialized value in printf. I dont get it.
        Hi it does work. I think I did some stupid thing but it works perfect now. Thanks a lot.