http://qs321.pair.com?node_id=965875

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

This is what I am trying:
my %info = (); open(IN,"<$file"); while(<IN>) { my $line = $_; chomp $line; my($lastname, $firstname, $country, $language) = split('\|', $ +line); #print"$lastname, $firstname, $country, $language\n"; $info{'lastname'} = $lastname; $info{'firstname'} = $firstname; $info{'country'} = $country; $info{'language'} = $language; }
But the way it is set up only the last data that the script read is what get displayed and the reason is same key. So how do I assign value so that each time it is different value get assigned to the same key. Thanks

Replies are listed 'Best First'.
Re: Can a single key have different value assigned to it
by Lady_Aleena (Priest) on Apr 19, 2012 at 06:53 UTC

    Hello, it looks like you may need to create an array of hashes, one hash for each $line. That way you get to keep all of your records.

    my @information; open(IN,"<$file"); while(<IN>) { my $line = $_; chomp $line; my($lastname, $firstname, $country, $language) = split('\|', $line +); #print"$lastname, $firstname, $country, $language\n"; push @information, { 'lastname' => $lastname, 'firstname' => $firstname, 'country' => $country, 'language' => $language, } }

    Update: I made a typo in the code, so I fixed it.

    Have a cookie and a very nice day!
    Lady Aleena
Re: Can a single key have different value assigned to it
by Anonymous Monk on Apr 19, 2012 at 06:54 UTC
      Thanks the very first one worked. I was just trying to understand how it was working. So when we do array of hash the each new indices of array will have new key and value that way we avoid overwriting of same key value right?

        You are correct. If you dump the data, you will see all of your data in an array of hashes.

        use Data::Dumper; print Dumper(\@information);
        Have a cookie and a very nice day!
        Lady Aleena

        It's a hash of arrays

        %info is a hash

        $info{lastnames} is an array reference

        To take a page out of Basic debugging checklist tutorial

        use Data::Dump; dd { lastnames => [ qw/ ro sham bo / ] }; __END__ { lastnames => ["ro", "sham", "bo"] }

        Hmm, lets try that again

        use Data::Dump; my %info; push @{ $info{lastnames} }, 'ro'; push @{ $info{lastnames} }, 'sham'; push @{ $info{lastnames} }, 'bo'; dd \%info; __END__ { lastnames => ["ro", "sham", "bo"] }

        Thats better. Last demo

        use Data::Dump; my %info; $info{lastnames}[0] = 'ro'; $info{lastnames}[1] = 'sham'; $info{lastnames}[2] = 'bo'; dd \%info; __END__ { lastnames => ["ro", "sham", "bo"] }

        Any time you're wondering about something , write yourself a little program like these three :) hashofarrays.01.pl, hashofarrays.02.pl, hashofarrays.03.pl

        Does a hash of arrays make sense for your use case, maybe :) maybe @records is a better fit, I can't tell yet

Re: Can a single key have different value assigned to it
by Tux (Canon) on Apr 19, 2012 at 09:31 UTC

    As an alternative, use Text::CSV or Text::CSV_XS and read the whole file in one go:

    use Text::CSV_XS; open my $fh, "<", $file or die "$file: $!"; my $csv = Text::CSV_XS->new ({ auto_diag => 1, binary => 1, sep_char = +> "|" }); $csv->column_names (qw( lastname firstname country language )); my $info = $csv->getline_hr_all ($fh);

    With your data looking like

    Wall|Larry|USA|English Walker|Johnny|Scotland|Scottish

    $info (an arrayref: a pointer to a list of hashes) would look like:

    [ { country => 'USA', firstname => 'Larry', language => 'English', lastname => 'Wall' }, { country => 'Scotland', firstname => 'Johnny', language => 'Scottish', lastname => 'Walker' } ]

    Enjoy, Have FUN! H.Merijn
Re: Can a single key have different value assigned to it
by JavaFan (Canon) on Apr 19, 2012 at 09:04 UTC
    So how do I assign value so that each time it is different value get assigned to the same key.
    You'd use a second index. For instance:
    my $count; while (my $line = <IN>) { chomp $line; my($lastname, $firstname, $country, $language) = split(/\|/, $line +); $info{lastname}[$count] = $lastname; $info{firstname}[$count] = $firstname; $info{country}[$count] = $country; $info{language}[$count] = $language; $count++; }
    Or, (untested), do it all at once, and benefit fully from using strict:
    my $LASTNAME = 0; my $FIRSTNAME = $LASTNAME + 1; my $COUNTRY = $FIRSTNAME + 1; my $LANGUAGE = $COUNTRY + 1; my @info = map {[/[^|\n]*/g]} <IN>;
    Note that this reverses the role of the indices compared to my first suggestion -- and stores the row level data in arrays instead of hashes.
Re: Can a single key have different value assigned to it
by sundialsvc4 (Abbot) on Apr 19, 2012 at 12:33 UTC

    You will need to define, say, an array(ref) of hash(refs), or vice-versa as you prefer.   This can be done more easily than you might suppose, thanks to Perl’s so-called “auto-vivication” features.   Consider the following two “Perl one-liner” examples:   (the command, followed by its output)

    $ perl -e 'my $h; my $k="foo"; push @{$$h{k}}, "bar"; use Data::Dumper +; print Data::Dumper->Dump([$h], ["h"]);' $h = { 'k' => [ 'bar' ] };
    or ...
    $ perl -e 'my $h; my $k="foo"; push @{$$h{k}{"name"}}, "bar"; use Data +::Dumper; print Data::Dumper->Dump([$h], ["h"]);' $h = { 'k' => { 'name' => [ 'bar' ] } };

    In each case, you can see that, simply as a matter of due course while executing a push statement, the entire data structure to which I intended to push the value simply “came to life automatically” as-needed if it didn’t exist already.   Since in this simple case nothing existed, this is what happened:

    • $h simply became a hashref;
    • It simply acquired the key “k”, and in the second case, nested hashrefs;
    • The entry simply became an empty arrayref, and a value was pushed onto it.

    You don’t have to bother to consider, “well, does it exist yet?”   If you need it, and it doesn’t yet, then presto!, it does.   Not quite “let there be light, and there was light,” but pretty darned close.   This is one of the many reasons why Perl is so often called the Swiss Army® Knife of pragmatic data processing.

Re: Can a single key have different value assigned to it
by biohisham (Priest) on Apr 20, 2012 at 10:54 UTC
    I think for you this is going to be the best time in your Perl journey to start becoming aware of the strength of Data Structures lent to text processing. Perl, in addition to it's robust regular expressions can as well enable you handle text to your fancy by using a combination of Arrays and Hashes nested within each other to any depth. Start from the following on the Tutorials and I am sure you will never fall short of tricks in front of any text processing task.

    References is a good start, if you learn how to reference and dereference then you are well on your way.


    David R. Gergen said "We know that second terms have historically been marred by hubris and by scandal." and I am a two y.o. monk today :D, June,12th, 2011...