Data::Dumper certainly cleared that up (I had never used this before, and this will become a favorite.)
It works both ways: if you can write down your data structure in a manner that looks like Data::Dumper output, then you can be relatively sure your data is at least syntactically correct.

Anyway. If I get you right, you're reading Set One, which would result in the hash as defined in Listing 1, and then you're reading Set Two, which would alter the original hash to that it becomes the one as defined in Listing Two.

# Listing One: %hash = ( "123" => "abc", "456" => { # I'm chosing for a hashref here becaus +e "abc" => undef, # eventually we'll possibly replacing t +hose "xyz" => undef, # undefs with something else. } "789" => "abc" );
# Listing Two: %hash = ( "123" => {"abc" => "zzz"}, "456" => { "abc" => ["xxx", "yyy"], "xyz" => undef # Or [], or 0, or "", or whatev +er }, "789" => {"abc" => "xxx"} );
use strict; use warnings; use Data::Dump 'pp'; # Or Data::Dumper, but I prefer the pp output. # Note that I'm using scalars here to represent the files. # I'm using Perl's capability to use references-to-scalars # as if they were files. my $setOne = <<EOF abc 123 abc 456 abc 789 xyz 456 EOF ; my $setTwo = <<EOF xxx ==> 456->abc xxx ==> 789->abc yyy ==> 456->abc yyy ==> 456->abc zzz ==> 123->abc EOF ; my %hash; # See? Here I'm opening a file handle to read from $setOne. # Typically, you'd put "somefilename.txt" in place of \$setOne, # but this code if for demonstration purposes only. open my $fileOne, "<", \$setOne or die "Couldn't read set one: $!"; while (my $line = <$fileOne>) { chomp $line; # Goodbye, newlines characters. # It would seem like the order of values and keys is turned around # in the file for set one. That, or I misinterpreted your intentio +n. my ($value, $key) = split(/\s+/, $line); if (ref $hash{$key}) { # If $hash{"123"} already is a reference, then we can just add + the new # key to it. # Note that the name '$value' is a little misleading here, sin +ce we'll # be using it as a key... Well, such is life. $hash{$key}->{$value} = undef; } elsif (exists $hash{$key}) { # $hash{"123"} is already there, but we got another value for +it. # So we need a hash ref. Let's make one. $hash{$key} = {$hash{$key} => undef, $value => undef}; } else { # $hash{"123"} isn't there yet, so here we go rather plainly: $hash{$key} = $value; } } close $fileOne; # Let's see what we've got so far. pp \%hash; # print Dumper \%hash; # Again, I prefer pp, but there are always + multiple options. # Fine then. Let's read that other file. open my $fileTwo, "<", \$setTwo or die "Couldn't read set two: $!"; while (my $line = <$fileTwo>) { chomp $line; my ($newvalue, $key, $oldvalue) = $line =~ m/^(.+)\s+==>\s+(.+)->( +.+)$/; if (ref $hash{$key}) { # If $hash{"123"} is a reference... if (ref $hash{$key}->{$oldvalue}) { # If $hash{"123"}->{"abc"} is also a reference # Jump right to the next iteration if we've run into a dup +licate. # Since your original example didn't specify that it shoul +d take # duplicates into account. next if grep {$_ eq $newvalue} @{$hash{$key}->{$oldvalue}} +; push @{$hash{$key}->{$oldvalue}}, $newvalue; } elsif (exists $hash{$key}->{$oldvalue}) { # $hash{"123"}->{"abc"} is not a reference, even though # it already exists. if (defined $hash{$key}->{$oldvalue}) { # This means that $hash{"123"}->{"abc"} already has a +value, # so what we really need here is to convert it into an + array ref # so that it can hold multiple values. $hash{$key}->{$oldvalue} = [$hash{$key}->{$oldvalue}, +$newvalue]; } else { # $hash{"123"}->{"abc"} is undef, so we can simply rep +lace # the undef with the new value. $hash{$key}->{$oldvalue} = $newvalue; } } } else { # $hash{"123"} is not a reference yet. Let's turn it into one. $hash{$key} = {$oldvalue => $newvalue}; } } close $fileTwo; # Final results: pp \%hash;

But really, this is such a mess that I doubt this is what you want.


In reply to Re^3: (another) HoH question by muba
in thread (another) HoH question by zuma53

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.