beethamd has asked for the wisdom of the Perl Monks concerning the following question:

I have this code in a loop which runs a large regexp from a very large text file. Each line in the file has one of seven different dates. I want to create %2007111, say, then %20071112 as required. If the hash already exists then I do stuff to the hash. Could anyone help me? (first post)
$date = $4.$3.$2; if (eval("\%$date")) { print "<TD class=table_font>$date - Hash exists</TD>\n"; # play with hash } else { print "<TD class=table_font>$date - Hash doesn't exist</TD>\n"; # create the hash eval("\%$date = ()"); # play with hash }
David

Replies are listed 'Best First'.
Re: Dynamically creating a hash based on a variable
by Joost (Canon) on Apr 15, 2007 at 13:54 UTC
    This question gets asked a lot, and the answer is almost always "don't do that".

    It's better to use a hash-of-hashes instead:

    # set up the base hash my %hashes = (); # in the loop: my $date = $4.$3.$2; if (my $hashref = $hashes{$date}) { print "<TD class=table_font>$date - Hash exists</TD>\n"; # play with hash } else { my $hashref = {}; # create a new empty hash $hashes{$date} = $hashref; store the hashref in the main hash print "<TD class=table_font>$date - Hash doesn't exist</TD>\n"; # play with hash }
    See also perlreftut and perldata.

      Joost - That's wonderful. Thank you very much for the reply.
Re: Dynamically creating a hash based on a variable
by cdarke (Prior) on Apr 15, 2007 at 13:54 UTC
    I hope I have interpreted your question correctly, if not apologies.
    You can find out if the hash exists with: if defined. However, you might consider another way of doing this. I suggest you create a single hash where the keys are the dates. The value to each key would be a reference to an anonymous hash, like this:
    $hash{$date} = {};
    To "play with the hash", adding values would be:
    $hash{$date}->{key} = value;
    To see if the hash exists, use exists:
    if (exists $hash{$date}) {...}
      Thank you - Seems I need to read about hashes tonight.
Re: Dynamically creating a hash based on a variable
by GrandFather (Saint) on Apr 15, 2007 at 13:57 UTC

    It may be that you want something like:

    use strict; use warnings; my %dates; while (<DATA>) { next unless /(.)(..)(..)(.{4})/; my $date = "$4$3$2"; if (exists $dates{$date}) { print "<TD class=table_font>$date - Hash exists</TD>\n"; # play with hash } else { print "<TD class=table_font>$date - Hash doesn't exist</TD>\n" +; # create the hash $dates{$date} = undef; # play with hash } } __DATA__ x11112007 y11122007 p11112007 x11132007

    Prints:

    <TD class=table_font>20071111 - Hash doesn't exist</TD> <TD class=table_font>20071211 - Hash doesn't exist</TD> <TD class=table_font>20071111 - Hash exists</TD> <TD class=table_font>20071311 - Hash doesn't exist</TD>

    Note that it helps a lot to understand what you are trying to do if you provide a little data and tell us what you expect to see and what you actually see.


    DWIM is Perl's answer to Gödel
Re: Dynamically creating a hash based on a variable
by naikonta (Curate) on Apr 15, 2007 at 16:36 UTC
    my $state = $hash{$date}++ ? 'exists' : "doesn't exist"; print qq(<TD class="table_font">$date - Hash $state</TD>\n);
    Or, if you really want to play with it,
    if ($hash{$date}++) { print qq(<TD class="table_font">$date - Hash exists</TD>\n); } else { print qq(<TD class="table_font">$date - Hash doesn't exist</TD>\n); }

    Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!