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

Fellow monks,

I've got 2 files containing customer names and year to date purchases. The files should each contain the same customers, although the second file may have new entries or have lost entries. My thought was to put this in to an anonymous hash so that I could match up customers with their YTD purchases. So far so good. (The data is comma delimited with quotes around the customer name, hence the regex.)

The problem arose when I tried to use the following code:

open FH, $file1; while (chomp($line = <FH>)){ $line =~ s/"//g; ($key,$ytd{$key}->{oct01}) = split(',',$line); } close FH;

My results were that I would get the first line's YTD value out, but not the customer. Next line would have the first line's customer and the second line's YTD value. Very odd.

However when I changed to this:

open FH, $file1; while (chomp($line = <FH>)){ $line =~ s/"//g; ($key,$temp) = split(',',$line); $ytd{$key}->{oct01} = $temp; } close FH;

all worked like a champ.

So this brings me to my quest for some understanding and instruction. Is it possible to split file data in to an anonymous hash? I really don't understand why it didn't work assigning the value to the anon hash directly. I'd rather do it in the one line rather than have to use the temp variable.

There is no emoticon for what I'm feeling now.

Replies are listed 'Best First'.
Re: Splitting file data in to anonymous hashes
by jdporter (Paladin) on Dec 13, 2002 at 18:38 UTC
    You can do the assignment in one line, but it's kinda tricky.
    Note that you still need a temporary; it just doesn't have to be a named temporary.
    while (<FH>) { chomp; $ytd{ $_->[0] }{'oct01'} = $_->[1] for [ split ',' ]; }
    (Note the better style. Using $line instead of $_ just makes your code noisier and more error prone.)

    jdporter
    ...porque es dificil estar guapo y blanco.

Re: Splitting file data in to anonymous hashes
by MarkM (Curate) on Dec 13, 2002 at 17:55 UTC

    Your problem is actually very simple to solve, and you have the correct solution above.

    Perl evaluates $ytd{$key}->{oct01} before it evaluates $key and assigns $key and $ytd{$key}->{oct01} values.

    You need that $temp variable.

Re: Splitting file data in to anonymous hashes
by Mr. Muskrat (Canon) on Dec 13, 2002 at 17:55 UTC

           ($key,$ytd{$key}->{oct01}) = split(',',$line);

    Each time through the loop, this line sets $key to the customer name. It also sets $ytd{$key}->{oct01} to the YTD value but it's using the previous value of $key since $key is set at the same time. So the first time through, it sets $ytd{''}->{'oct01'}

Re: Splitting file data in to anonymous hashes
by Eimi Metamorphoumai (Deacon) on Dec 13, 2002 at 17:55 UTC
    The problem isn't the anonymous hash, the problem is the atomic assignment. That is, you're simultaneously assigning a value to $key, and trying to use the new value of $key as a key. Instead, you're getting the old value of $key, which is why all your data is off by one. I can't think of a way to do it in one line, since you really are making two assignments where the second depends on the first.
      Thank you for explaining that, now it makes sense. It was driving me nuts last night as I was looking at the output.

      Just one more example of: "Get it to work before you try to optimize!"

      There is no emoticon for what I'm feeling now.

Re: Splitting file data in to anonymous hashes
by CountZero (Bishop) on Dec 13, 2002 at 18:42 UTC

    And if you would have declared your variables $line and $key inside the while loop with "my" the error would have been more obvious.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law