in reply to Count number of elements in HoH and sum them for other keys

G'day Sosi,

Parsing tab-, comma-, whatever-separated files has various issues that have already been dealt with by Text::CSV [see also: Text::CSV_XS and Text::CSV_PP]. This is probably not a wheel you need to reinvent: I've shown usage of Text::CSV in the example code (below).

Your output data structure is flawed. You have instances of this general code:

X => { count => n, [ ... ] }

You have three elements in the hashref, which is a problem: key/values pairs result in an even number of elements. That generates an "Odd number of elements in anonymous hash" warning.

In the example code (below), I've added a "values" key for both the arrayref (i.e. the third element) and the top-level key.

X => { count => n, values => [ ... ] }

Here's the example code:

#!/usr/bin/env perl -l use strict; use warnings; use autodie; use Text::CSV; my $csv = Text::CSV::->new({sep_char => "\t"}); my %data; while (my $row = $csv->getline(\*DATA)) { ++$data{$row->[0]}{count}; ++$data{$row->[0]}{values}{$row->[1]}{count}; push @{$data{$row->[0]}{values}{$row->[1]}{values}}, $row->[2]; } use Data::Dump; dd \%data; __DATA__ A B n1 A B n2 A C n1 D E n2 D E n4 D F n1

Which outputs:

{ A => { count => 3, values => { B => { count => 2, values => ["n1", "n2"] }, C => { count => 1, values => ["n1"] }, }, }, D => { count => 3, values => { E => { count => 2, values => ["n2", "n4"] }, F => { count => 1, values => ["n1"] }, }, }, }

-- Ken

Replies are listed 'Best First'.
Re^2: Count number of elements in HoH and sum them for other keys (sledgehammer)
by Anonymous Monk on Jun 03, 2014 at 16:50 UTC

    > Parsing tab-, comma-, whatever-separated files has various issues that have already been dealt with by Text::CSV

    Like what?

    That module deals with all the features and intricacies of the 'official' CSV format, such as quoting/escaping and embedding newlines/NULLbytes. But the OP never specified the input data be in that complex format; from the looks of it it's just simple ASCII strings delimited by tabs and newlines. No need to take a sledgehammer to crack a nut...

    > This is probably not a wheel you need to reinvent

    Applying a simple, tried-and-true Perl idiom is not much of an 'invention':

    while(<>) { my @fields = split /\t/; ... }