in reply to Re^2: Counting elements in array of cases
in thread Counting elements in array of cases

It's destructive => There was no requirement to not do that. I'll resort to my old saying "If it passes all the test cases, it's correct :)"

Repeated splits => Just concatenate as we go, and fix up right before the end. Is it really faster? I don't know and I don't care :)

Like so:

#!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11106779 use warnings; use List::Util qw( uniq ); my @AoH = ( { count => 1, origin => "AMG", targetL => "foisonnement" }, { count => 1, origin => "IDBR", targetL => "foisonnement" }, { count => 1, origin => "IWWF", targetL => "gonfler" }, { count => 1, origin => "IWWF", targetL => "due" }, { count => 1, origin => "IWWF", targetL => "due" }, ); my %seen; my @AoHfinal = grep { $_->{origin} = join ' ', uniq split ' ', $_->{or +igin} } map { if( my $prev = $seen{$_->{targetL}} ) { $prev->{count} += $_->{count}; $prev->{origin} .= ' ' . $_->{origin}; () # skip duplicate } else { $seen{$_->{targetL}} = { %$_ }; } } @AoH; use Data::Dump 'dd'; dd @AoHfinal;

Replies are listed 'Best First'.
Re^4: Counting elements in array of cases
by tybalt89 (Monsignor) on Sep 27, 2019 at 21:09 UTC

    Using a for instead of that grep

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11106779 use warnings; use List::Util qw( uniq ); my @AoH = ( { count => 1, origin => "AMG", targetL => "foisonnement" }, { count => 1, origin => "IDBR", targetL => "foisonnement" }, { count => 1, origin => "IWWF", targetL => "gonfler" }, { count => 1, origin => "IWWF", targetL => "due" }, { count => 1, origin => "IWWF", targetL => "due" }, ); my %seen; $_->{origin} = join ' ', uniq split ' ', $_->{origin} for my @AoHfinal + = map { if( my $prev = $seen{$_->{targetL}} ) { $prev->{count} += $_->{count}; $prev->{origin} .= ' ' . $_->{origin}; () # skip duplicate } else { $seen{$_->{targetL}} = { %$_ }; # copy hash so not destructive } } @AoH; use Data::Dump 'dd'; dd @AoHfinal;
Re^4: Counting elements in array of cases
by rsFalse (Chaplain) on Sep 27, 2019 at 22:35 UTC
    Here, I tried to change tybalt89's code by including one more hash deeper instead of uniq:
    #!/usr/bin/perl # https://perlmonks.org/?node_id=11106779 use strict; use warnings; use Data::Dumper; my @AoH = ( { count => 1, origin => "AMG", targetL => "foisonnement" }, { count => 1, origin => "IDBR", targetL => "foisonnement" }, { count => 1, origin => "AMG", targetL => "foisonnement" }, { count => 1, origin => "IWWF", targetL => "gonfler" }, { count => 1, origin => "IWWF", targetL => "due" }, { count => 1, origin => "IWWF", targetL => "due" }, ); my %seen; my @AoHfinal = # map { delete $_->{origins}; $_ } map { if( my $prev = $seen{$_->{targetL}} ) { $prev->{count} += $_->{count}; if( not exists $prev->{origins}{ $_->{origin} } ){ $prev->{origin} .= ' ' . $_->{origin}; $prev->{origins}{ $_->{origin} } ++; } () # skip duplicate } else { $_->{origins}{ $_->{origin} } ++; $seen{$_->{targetL}} = { %$_ }; } } @AoH; print Dumper( \@AoHfinal );
    OUTPUT:
    $VAR1 = [ { 'count' => 3, 'origin' => 'AMG IDBR', 'targetL' => 'foisonnement', 'origins' => { 'IDBR' => 1, 'AMG' => 1 } }, { 'count' => 1, 'targetL' => 'gonfler', 'origin' => 'IWWF', 'origins' => { 'IWWF' => 1 } }, { 'count' => 2, 'origins' => { 'IWWF' => 1 }, 'origin' => 'IWWF', 'targetL' => 'due' } ];
Re^4: Counting elements in array of cases
by LanX (Saint) on Sep 27, 2019 at 18:04 UTC
    > There was no requirement to not do that.

    Sure, as so often requirements are ambiguous and interpretations vary, that's why I added side notes.

    Anyway I like the approach a lot, this pattern is not too often applied.

    But I was probably also overmotivated because I understood your code... ;)

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