Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Perl hashes: is there some way of adding more data to the value associated with an existing key?

by mertserger (Curate)
on Jun 07, 2011 at 14:40 UTC ( #908489=perlquestion: print w/ replies, xml ) Need Help??
mertserger has asked for the wisdom of the Perl Monks concerning the following question:

I have some data I have extracted using SQl from a database. It takes the form of a list of two related values, which are an id number and then a value. Unfortunately the id number can be in the list more than once with a different value in the second column:
1 A 1 B 2 B 4 X 5 V
etc. I really need this to end up in a hash where the key is the id number but the value is the combined values of all the second columns, so in the made-up example above key "1" would relate to a value "A B". I know how to create a hash which would either take the first pair or last pair of key/value but I am struggling to see how you could update the value for the key so that it would contain all the values associated with that key.

Comment on Perl hashes: is there some way of adding more data to the value associated with an existing key?
Download Code
Re: Perl hashes: is there some way of adding more data to the value associated with an existing key?
by Eliya (Vicar) on Jun 07, 2011 at 14:53 UTC

    The value of a hash entry is a scalar, but this scalar can be a reference to an array, into which you can put more than one value:

    push @{ $hash{$id} }, $val;

    Also, Perl features autovivification, so you don't need to worry about the initial case when there is no array(ref) yet — i.e. Perl implicitly creates it for you.

Re: Perl hashes: is there some way of adding more data to the value associated with an existing key?
by choroba (Abbot) on Jun 07, 2011 at 14:53 UTC
    Use hash of arrays, see perldsc. Example:
    my %h = ( 1 => ['A', 'B'], 2 => ['B'], 4 => ['X'], 5 => ['V'], ); print join(' ', @{ $h{1} }),"\n";
Re: Perl hashes: is there some way of adding more data to the value associated with an existing key?
by wind (Priest) on Jun 07, 2011 at 15:54 UTC
    Just use a hash of arrays.
    use strict; use warnings; my %data; while (<DATA>) { chomp; my ($k, $v) = split; push @{$data{$k}}, $v; } use Data::Dumper; print Dumper(\%data); __DATA__ 1 A 1 B 2 B 4 X 5 V

      Note:   Just to be absolutely clear about what this is ... it is a hash of array references.   (“Arrayrefs.”)

      The thing that is in a particular slot, of an array or of a hash or of a list, is always “a single value,” but one of the possible “values” that it can be, is “a reference to” absolutely anything else.   This is the magic of Perl data structuring, and one of the hallmark features of the language.   It allows arbitrary (and efficient!) data structures to be built out of a handful of simple primitives.

Re: Perl hashes: is there some way of adding more data to the value associated with an existing key?
by danb (Friar) on Jun 07, 2011 at 16:12 UTC

    It's generally a lot better (faster, cleaner, clearer) to do this type of stuff in the database. All you need is an aggregate function that concatenates strings with a space delimiter. Here are several ways to do it for PostgreSQL, SQL Server, and MySQL:

    String Aggregation in PostgreSQL, SQL Server, and MySQL - Postgres OnLine Journal

    With Postgres and DBD::Pg you can get an actual array instead of a delimited string.

    --Daniel

      Thanks to everyone for their replies.

      As Daniel pointed out, the best way was to do this in the SQL, but I wasn't sure if you could. I have yet to find a website for SQL monks! However with Daniel's pointer I found the useful Oracle function wm_concat which does what I want to data and which I never knew about before.

      You learn something every day and as always: there is more than one way to do things.
        TMTOWTDI: I like to think of awk as baby perl - a really fast baby.
        awk '{ seen[$1] = $2","seen[$1] ; } END { for (key in seen) { print key" "seen[key] ; } } ' /your/file.txt > /your/newfile.txt

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://908489]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2014-08-01 07:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (257 votes), past polls