Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Need to get hash of arrays

by chandantul (Scribe)
on May 14, 2021 at 05:54 UTC ( [id://11132563]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Smart monks, I have the data looks like below in separate columns and i will need to get the unique values of columns A and assign multiple values of column B Please check below data structure

ColA | ColB | 500001| Network1| 500001| Network2| 500002| Network2| 500003| Network1| 500003| Network3|</

I will need to assign all corrosponding values of Column B to the unique value of Column A , This will be looks like below

$var1 => {500001 => Network1 , Netowrk2} {500002 => Netowrk2} {500003 => Netowrk1 , Netowrk3}

I have tried by below Hash mapping but its coming with one to one mapping but i will need one to multi mappings

@hash4{@cellp} = [@cellq];

Code output

{500001 => Netowrk2} {500002 => Netowrk2} {500003 => Netowrk3}

Can you please help with proper assignment?

Replies are listed 'Best First'.
Re: Need to get hash of arrays -- plain english
by Discipulus (Canon) on May 14, 2021 at 06:12 UTC
    Hello chandantul,

    Firstly read perldsc then you can try this approach:

    while reading the file, chomp the line, split the line using '| ' havi +ng back col1 and col2 then push into the hash key col1 the value of c +ol2. Hint: being values of the hash all arrayrefs you need some deref +encing like in @{ $hash{ $col1 } } doing the push.

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Need to get hash of arrays
by hippo (Bishop) on May 14, 2021 at 11:03 UTC
Re: Need to get hash of arrays
by BillKSmith (Monsignor) on May 14, 2021 at 12:51 UTC
    The Command Switches -a, -F, and -n do most of the work.
    #!perl -aF/\|/ -n use strict; use warnings; our %hash; push @{$hash{$F[0]}}, $F[1]; END{ use Data::Dumper; print Dumper(\%hash); }
    Bill
Re: Need to get hash of arrays -- oneliner
by Discipulus (Canon) on May 14, 2021 at 09:46 UTC
    As you are collecting solutions.. and dealing with highly malformed data..

    perl -MData::Dump -F"\|\s?" -lane "$.==1?next:push@{$h{eval$F[0]=~tr/\ +s//r}},$F[1]}{dd%h" columndata.txt ( 500002, ["Network2"], 500003, ["Network1", "Network3"], 500001, ["Network1", "Network2"], )

    which deparsed gives:

    perl -MO=Deparse -MData::Dump -F"\|\s?" -lane "$.==1?next:push@{$h{eva +l$F[0]=~tr/\s//r}},$F[1]}{dd%h" columndata.txt BEGIN { $/ = "\n"; $\ = "\n"; } use Data::Dump; LINE: while (defined($_ = readline ARGV)) { chomp $_; our @F = split(/\|\s?/, $_, 0); $. == 1 ? next : push(@{$h{eval $F[0] =~ tr/s//r};}, $F[1]); } { dd(%h); } -e syntax OK

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Need to get hash of arrays
by AnomalousMonk (Archbishop) on May 14, 2021 at 08:58 UTC

    What Discipulus said:

    Win8 Strawberry 5.8.9.5 (32) Fri 05/14/2021 4:48:55 C:\@Work\Perl\monks\workInProgress12 >perl use strict; use warnings; use autodie; use Data::Dump qw(dd); my $data = <<'EOD'; ColA | ColB | 500001| Network1| 500003| Network1| 500002| Network2| 500001| Network2| 500003| Network3| EOD open my $fh, '<', \$data; <$fh>; # ignore headings record/line my %hash4; while (<$fh>) { my ($k, $v) = map { (my $r = $_) =~ s{ \A \s+ | \s+ \z }{}xmsg; $r; } split /\s*\|\s*/ #splits $_ implicitly ; # print "\$k '$k' \$v '$v' \n"; # for debug push @{ $hash4{$k} }, $v; } dd \%hash4; close $fh; ^Z { 500001 => ["Network1", "Network2"], 500002 => ["Network2"], 500003 => ["Network1", "Network3"], }
    You really should know all this by now. (sigh)


    Give a man a fish:  <%-{-{-{-<

      Or with Text::CSV/Text::CSV_XS:

      use warnings; use strict; use Data::Dump; use Text::CSV; # also install Text::CSV_XS for speed my %data; my $csv = Text::CSV->new({ binary=>1, auto_diag=>2, sep_char=>"|", allow_whitespace=>1 }); my $hdr = $csv->getline(*DATA); while ( my $row = $csv->getline(*DATA) ) { push @{ $data{ $row->[0] } }, $row->[1]; } $csv->eof or $csv->error_diag; dd \%data; __DATA__ ColA | ColB | 500001| Network1| 500001| Network2| 500002| Network2| 500003| Network1| 500003| Network3|

        Hello Smart Monks, Thanks for your help. I have fixed this by below assignment

        push @{ $hash4{$cellp[$_]} }, $cellr[$_] for (0..$#cellp);

        I have fixed by below and lable as appropriate about within network or no network users

        if (grep { grep { $_ eq "No Network" } @{$hash4{$celln[$o]}} } keys %h +ash4) { worksheet->write($r12, 2, "Non Network"); }

        Thanks for your help.

      > You really should know all this by now. (sigh)

      why learning if he gets it for free? (sigh ;)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        True, true...


        Give a man a fish:  <%-{-{-{-<

Re: Need to get hash of arrays
by 1nickt (Canon) on May 14, 2021 at 09:59 UTC

    Hi,

    By the pipe separator it looks like you are retrieving the data from a MySQL or other database. Is that the case? If so you can populate your hash of arrays while you are fetching the results from the DB.

    while ( my $row = $sth->fetchrow_arrayref ) { push( @{ $hash{$row->[0]} }, $row->[1] ); }

    Hope this helps!


    The way forward always starts with a minimal test.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-03-29 09:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found