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 (Abbot) 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 (Chancellor) on May 14, 2021 at 11:03 UTC
Re: Need to get hash of arrays
by BillKSmith (Prior) 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 (Abbot) 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 1nickt (Abbot) 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.
Re: Need to get hash of arrays
by AnomalousMonk (Bishop) 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:  <%-{-{-{-<