in reply to Re^3: Perl Hash
in thread Perl Hash

thanks Dave, I've got past the "not declaring my $k further up the program" problem now :)

but it appears my problem is what "not Keith" says

>> You also seem to think that you can have multiple values for a single key. That's not true,

well in that case, I do have a problem as I want to store several lines of text against the same key like this



KEY1 07/25/05 09:04:36 KEY2 07/25/05 09:04:36 KEY2 07/25/05 09:04:37 KEY2 07/25/05 09:05:49 KEY2 07/25/05 09:05:50 KEY3 07/25/05 09:05:50


so then I can find the earliest time in KEY2 is 09:04:36 and the latest time is 09:05:50

However, now I'll have to find another way.

Thanks for your help.

Replies are listed 'Best First'.
Re^5: Perl Hash
by davorg (Chancellor) on Jul 26, 2005 at 09:51 UTC
    I want to store several lines of text against the same key

    Then you want the values in your hash to be array references.

    You should probably read perldsc.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re^5: Perl Hash
by GrandFather (Saint) on Jul 26, 2005 at 09:55 UTC

    A Hash of arrays may fit the bill for you:

    use strict; use warnings; use Data::Dumper; my %HoA; while (<DATA>) { chomp; next if ! length $_; my ($key, $time) = split ","; push @{$HoA{$key}}, $time; } print Dumper (%HoA);

    Perl is Huffman encoded by design.
Re^5: Perl Hash
by GrandFather (Saint) on Jul 26, 2005 at 10:15 UTC

    or if you rather just retain the first and last time for each key for which there is more than one time:

    use strict; use warnings; use Data::Dumper; my %HoA; while (<DATA>) { chomp; next if ! length $_; my ($key, $time) = split ","; if (! $HoA{$key}) {push @{$HoA{$key}}, $time;} elsif (@{$HoA{$key}} == 1) {push @{$HoA{$key}}, $time;} else {${@{$HoA{$key}}}[1] = $time;} } print Dumper (%HoA);

    Perl is Huffman encoded by design.
Re^5: Perl Hash
by Random_Walk (Prior) on Jul 26, 2005 at 10:02 UTC

    As your data looks to be time sequential something easy like this would probably do you fine. I have given a simple way to do it with two hashes or a more perlish way with a hash of arrays. If your data lines are not ordered by time then a check to compare two time stamps will be needed for each line to decide if to update first or last time.

    #!/usr/opt/perl5/bin/perl use strict; use warnings; use Data::Dumper; my %earliest; my %latest; my %hash_of_arrays; my $line; while ($line = <DATA>) { chomp $line; # remove return my ($key, $date) = split /\s+/, $line, 2; # split on space into ma +x 2 parts next unless $date; # ignore blank or malfor +med lines unless (defined $earliest{$key}) { $earliest{$key} = $date; } $latest{$key} = $date; # or with a hash of arrays $hash_of_arrays{$key} or $hash_of_arrays{$key}[0]=$date; $hash_of_arrays{$key}[1]=$date; } print Data::Dumper->Dump([\%earliest], ['%earliest']) ; print Data::Dumper->Dump([\%latest], ['%latest']); print Data::Dumper->Dump([\%hash_of_arrays], ['%hash_of_arrays']); print "first time for KEY1 was: $hash_of_arrays{KEY1}[0]\n"; print "last time for KEY1 was: $hash_of_arrays{KEY1}[1]\n"; __DATA__ KEY1 07/25/05 09:04:36 KEY2 07/25/05 09:04:36 KEY2 07/25/05 09:04:37 KEY2 07/25/05 09:05:49 KEY2 07/25/05 09:05:50 KEY3 07/25/05 09:05:50 KEY1 07/25/05 09:06:36 # output =>./first $%earliest = { 'KEY2' => '07/25/05 09:04:36', 'KEY1' => '07/25/05 09:04:36', 'KEY3' => '07/25/05 09:05:50' }; $%latest = { 'KEY2' => '07/25/05 09:05:50', 'KEY1' => '07/25/05 09:06:36', 'KEY3' => '07/25/05 09:05:50' }; $%hash_of_arrays = { 'KEY2' => [ '07/25/05 09:04:36', '07/25/05 09:05:50' ], 'KEY1' => [ '07/25/05 09:04:36', '07/25/05 09:06:36' ], 'KEY3' => [ '07/25/05 09:05:50', '07/25/05 09:05:50' ] }; first time for KEY1 was: 07/25/05 09:04:36 last time for KEY1 was: 07/25/05 09:06:36

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!
Re^5: Perl Hash
by Iron (Scribe) on Jul 26, 2005 at 09:58 UTC
    Is it necessary to use hashes or more complicated data structures? What about simple array?
    my @times; while (<LOGFILE>){ if (/\b$Autosys/) { push @times, substr($_, 0, 20); } }

    Update: yes, you can downvote me, 'cause HoA is the best way here. I misunderstand post. Shame on me.