[Chicago-talk] Combine like hash elements

Steven Lembark lembark at wrkhors.com
Mon Nov 23 09:28:40 PST 2015


On Mon, 23 Nov 2015 10:10:41 -0600
richard at rushlogistics.com wrote:

> I have a hash reference with the following structure:
> 
> {
> '11' => {'AMOUNT' => '20.00','ID' => '11','NAME' => 'Lincoln Park'},
> '12' => {'AMOUNT' => '38.00','ID' => '12','NAME' => 'Bucktown'},
> '13' => {'AMOUNT' => '41.00','ID' => '12','NAME' => 'Lincoln Park'}
> }
> 
> Can anyone tell me how I can combine them by 'NAME' so that I would have:
> 
> {
> '11' => {'AMOUNT' => '61.00','ID' => '11','NAME' => 'Lincoln Park'},
> '12' => {'AMOUNT' => '38.00','ID' => '12','NAME' => 'Bucktown'},
> }

You don't seem to care about the keys (loosing key "13" wasn't
a problem). 

Q: Are the ID values important or could they be discarded?

If so then just make a new hash keyed by NAME and accumulate
the AMOUNT values:

    my %resultz = ();

    for( values %inputz )
    {
        my ( $name, $amt, $id )  = @{ $_ }{ qw( NAME AMOUNT ID ) };
        my $val
        = $resultz{ $name } ||= { ID => $id, NAME => $name };

        $val->{ AMOUNT }    += $amt;
    }

    # at this point %resultz is keyed by name with an id and amount
    # for each entry.

    %inputz = ();

    while( my ( $name, $val ) = each %resultz )
    {
        $inputz{ $val->{ ID } } = $val;
    }

    # at this point the original inputs hash is keyed by ID
    # with values having a name, accumulated amount, and id.
    # multiple id's are collapsed into a single ID with the 
    # value of the first record for that name.

-- 
Steven Lembark                                             3646 Flora Pl
Workhorse Computing                                   St Louis, MO 63110
lembark at wrkhors.com                                      +1 888 359 3508


More information about the Chicago-talk mailing list