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

Hello, This is probably easy but I guess I don't know the proper keyword to search for so I am asking here. I need to summarize or consolidate an array of values and build an array which identifies how many of each consolidated values there are. For example I have the following array: a a b c d d So I want a resulting pair of arrays that gives: a, 2 b, 1 c, 1 d, 2 What do I need? Thanks! Lars
  • Comment on Summarize or Consolidate array by value?

Replies are listed 'Best First'.
Re: Summarize or Consolidate array by value?
by xdg (Monsignor) on Jan 16, 2006 at 14:48 UTC

    Not sure why you want it as arrays -- this is ideal for a hash:

    my @array = qw( a a b c d d ); my %counts; $counts{$_}++ for @array; # if you really want arrays back at the end: my @keys = keys %counts; my @vals = values %counts;

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      Indeed, however I wonder if order counts for the OP, i.e.: should

      qw/a a b c d d a/

      map to

      user wants? (a => 2, b => 1, c => 1, d => 2, a => 1): # or (a => 3, b => 1, c => 1, d => 2);

      I guess the latter, but still preserving the input order, in which case the common technique for uniq'ing a list can be easily adapted to do it:

      my %saw; my @sum=map {$_ => $saw{$_}} grep !$saw{$_}++, @array;

      Now that I think of it, this can be even adapted for the former task, provided that grep's selection is improved to delete the key is it's not the same as the previous one. I'd probably chose a completely different strategy, though.

Re: Summarize or Consolidate array by value?
by ikegami (Patriarch) on Jan 16, 2006 at 14:59 UTC
    If you want to preserve the order, use the following:
    my @array = qw( a a b c d d ); my %counts; my @keys = grep { !($counts{$_}++) } @array; print("$_: $counts{$_}\n") foreach @keys;
Re: Summarize or Consolidate array by value?
by davidrw (Prior) on Jan 16, 2006 at 14:50 UTC
    You probably want to hash up the array contents, where the keys of the hash will be the unique set of array elements and the values will be the times that that element occurs. There are many ways to write this out .. here is the start of one -- printing of the hash is left as an exercise for the reader .. Be sure to look up these hash-related functions in the docs: keys, values, each, exists
    use strict; use warnings; my %counts; foreach my $key ( @myArray ){ $counts{$key}++; }
Re: Summarize or Consolidate array by value?
by descolada (Initiate) on Jan 16, 2006 at 15:01 UTC
    Ah, thanks. So that's what all those hash chapters in the books are for :) Thanks for not chucking a RTFM at me...
Re: Summarize or Consolidate array by value?
by NiJo (Friar) on Jan 16, 2006 at 21:43 UTC
    A command line solution that should be older than perl:
    sort lines.txt | uniq -c
      Now that's good. Thank you!