http://www.perlmonks.org?node_id=11107128

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

Dear Monks,
i have a array structure like:

VAR1 = { 'Host' => 'server02', 'GroupName' => 'serversA' }; $VAR2 = { 'Host' => 'server04', 'GroupName' => 'serversA' }; $VAR3 = { 'GroupName' => 'serversB', 'Host' => 'server02' }; $VAR4 = { 'Host' => 'server04', 'GroupName' => 'serversB' }; $VAR5 = { 'GroupName' => 'serversC', 'Host' => 'server02' }; $VAR6 = { 'Host' => 'server04', 'GroupName' => 'serversC' }; $VAR7 = { 'GroupName' => 'serversD', 'Host' => 'server02' };
My expected output is:

server02 is in Groups serversA,serversB,serversC,serversD
server04 is in Groups serversA,serversB,serversC

I can do like "print $ref1->{Host} , " ", $ref1->{GroupName}, "\n";"
but how can i consolidate the values?

Thanks

Replies are listed 'Best First'.
Re: Array consolidating values
by haukex (Archbishop) on Oct 07, 2019 at 11:18 UTC
    use warnings; use strict; my @servers = ( { Host => 'server02', GroupName => 'serversA' }, { Host => 'server04', GroupName => 'serversA' }, { Host => 'server02', GroupName => 'serversB' }, { Host => 'server04', GroupName => 'serversB' }, { Host => 'server02', GroupName => 'serversC' }, { Host => 'server04', GroupName => 'serversC' }, { Host => 'server02', GroupName => 'serversD' }, ); my %hosts; for my $serv (@servers) { $hosts{ $serv->{Host} }{ $serv->{GroupName} }++; } for my $host (sort keys %hosts) { print "$host is in Groups ", join(',', sort keys %{$hosts{$host}}), "\n"; }
Re: Array consolidating values
by johngg (Canon) on Oct 07, 2019 at 14:43 UTC

    Noting that maikelnight usually provides code with questions, I don't mind cutting a little slack. As 1nickt suggests, iterate over @servers creating a HoA where the key is the "Host" and the value is an anonymous array onto which we push each "GroupName" as it is encountered. I've added another server that is in only one group and also shuffled the @servers array so as to show how to get sorted groups in the output. I also include Data::Dumper output to show the HoA structure. The code:-

    use 5.026; use warnings; use Data::Dumper; my @servers = ( { Host => q{server04}, GroupName => q{serversB}, }, { Host => q{server02}, GroupName => q{serversC}, }, { Host => q{server04}, GroupName => q{serversA}, }, { Host => q{server02}, GroupName => q{serversD}, }, { Host => q{server02}, GroupName => q{serversB}, }, { Host => q{server02}, GroupName => q{serversA}, }, { Host => q{server03}, GroupName => q{serversC}, }, { Host => q{server04}, GroupName => q{serversC}, }, ); my %inGroups; foreach my $rhServer ( @servers ) { push @{ $inGroups{ $rhServer->{ Host } } }, $rhServer->{ GroupName + }; } say Data::Dumper ->new( [ \ %inGroups ], [ qw{ *inGroups } ] ) ->Sortkeys( 1 ) ->Dumpxs(); say qq{Server $_ is in groups }, join q{, }, sort @{ $inGroups{ $_ } } for sort keys %inGroups;

    The output:-

    %inGroups = ( 'server02' => [ 'serversC', 'serversD', 'serversB', 'serversA' ], 'server03' => [ 'serversC' ], 'server04' => [ 'serversB', 'serversA', 'serversC' ] ); Server server02 is in groups serversA, serversB, serversC, serversD Server server03 is in groups serversC Server server04 is in groups serversA, serversB, serversC

    I hope this is of interest.

    Cheers,

    JohnGG

Re: Array consolidating values
by choroba (Cardinal) on Oct 07, 2019 at 14:59 UTC
    And here's how you can use a database to find out:
    #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; use DBI; my @servers = ( { Host => 'server02', GroupName => 'serversA' }, { Host => 'server04', GroupName => 'serversA' }, { Host => 'server02', GroupName => 'serversB' }, { Host => 'server04', GroupName => 'serversB' }, { Host => 'server02', GroupName => 'serversC' }, { Host => 'server04', GroupName => 'serversC' }, { Host => 'server02', GroupName => 'serversD' }, ); my $db = DBI->connect('dbi:SQLite:dbname=:memory:', "", ""); $db->do('CREATE TABLE servers (host TEXT, group_name TEXT)'); my $populate = $db->prepare('INSERT INTO servers VALUES(?, ?)'); $populate->execute($_->{Host}, $_->{GroupName}) for @servers; my $query = $db->prepare('SELECT host, GROUP_CONCAT(group_name) FROM s +ervers GROUP BY host'); $query->execute; while (my @row = $query->fetchrow_array) { say "@row"; }
    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Array consolidating values
by 1nickt (Canon) on Oct 07, 2019 at 13:26 UTC

    Hi, please show your code and how it fails to do what you want, not just your input and desired output (although those are needed too), else it looks like you just want someone to do your homework for you.

    In general, to build up a data structure like the one you need, you loop through the raw data and update a row in a table (using a Perl hash) by either pushing a value to a list, or incrementing a counter, contained at the key corresponding to the field in the data you are looking for.

    Hope this helps!


    The way forward always starts with a minimal test.

      I was fully aware i didnt provide code. and you can be sure that i spent hours trying to solve by myself and do homework. at least i didnt find an anchor. i just do perl at times. I would like to thank all of you. I havent tried all the solutions. the one from hauke did what i was looking for at first.

Re: Array consolidating values
by tybalt89 (Monsignor) on Oct 07, 2019 at 17:24 UTC
    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11107128 use warnings; my @servers = ( { Host => 'server02', GroupName => 'serversA' }, { Host => 'server04', GroupName => 'serversA' }, { Host => 'server02', GroupName => 'serversB' }, { Host => 'server04', GroupName => 'serversB' }, { Host => 'server02', GroupName => 'serversC' }, { Host => 'server04', GroupName => 'serversC' }, { Host => 'server02', GroupName => 'serversD' }, ); local $" = ' is in Groups '; $_ = join '', sort map "@{[ @$_{qw(Host GroupName)} ]}\n", @servers; 1 while s/^(.+$").*\K\n\1/,/m; print;

    Outputs:

    server02 is in Groups serversA,serversB,serversC,serversD server04 is in Groups serversA,serversB,serversC
Re: Array consolidating values
by BillKSmith (Monsignor) on Oct 07, 2019 at 19:18 UTC
    I think that you want to reorganize an array of hashes into a hash of arrays.
    use strict; use warnings; use Data::Dumper; my @servers = ( { Host => 'server02', GroupName => 'serversA' }, { Host => 'server04', GroupName => 'serversA' }, { Host => 'server02', GroupName => 'serversB' }, { Host => 'server04', GroupName => 'serversB' }, { Host => 'server02', GroupName => 'serversC' }, { Host => 'server04', GroupName => 'serversC' }, { Host => 'server02', GroupName => 'serversD' }, ); my %consolidated; foreach (@servers) { push @{$consolidated{$_->{Host}}}, $_->{GroupName}; } print Dumper(\%consolidated);
    OUTPUT: $VAR1 = { 'server02' => [ 'serversA', 'serversB', 'serversC', 'serversD' ], 'server04' => [ 'serversA', 'serversB', 'serversC' ] };
    Bill
Re: Array consolidating values
by LanX (Saint) on Oct 07, 2019 at 22:17 UTC
    could you please elaborate the kind of "consolidation" you expect?

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice