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

I have a script in Korn shell that creates a file of unique entries from a source file using the sort command below. I then count the number of times an entry appears in the source file with grep and wc.

Are there similar commands in Perl to uniquely sort an array, produce a new array and count how many times an entry appears in the original?

All I've found is a standard sort.

@modlist2 = sort (@modlist);
Parts of Korn Shell script:
sort -u modtype_2430.srt > modtype_2430.unq for k in `cat modtype_2430.unq` do if [ "$k" != 0 ] then type=$(grep $k modtype_2430.srt|wc -l)

Edit by tye, add formatting

Replies are listed 'Best First'.
Re: sorting arrays
by davido (Cardinal) on May 28, 2004 at 15:41 UTC
Re: sorting arrays
by eric256 (Parson) on May 28, 2004 at 15:52 UTC

    We can load the file into an array, loop through the array incrementing a hash using the entry as the key. Then loop through the hash sorted printing the value and the key.

    use strict; use warnings; my @lines = <DATA>; chomp @lines; my $saw = {}; $saw->{$_}++ foreach @lines; print "$saw->{$_} = $_\n" foreach sort keys %$saw; __DATA__ a b va sdf b a v b n a h

    Produces:

    3 = a 3 = b 1 = h 1 = n 1 = sdf 1 = v 1 = va

    ___________
    Eric Hodges
Re: sorting arrays
by sgifford (Prior) on May 28, 2004 at 16:06 UTC
    A tip on your ksh script: uniq -c will do most of what you want:
    sort modtype_2430.srt |uniq -c

    In Perl, you can do something similar by sorting the array, then walking through it:

    my @sorted = sort @array; my $last = shift @sorted; my $count = 1; foreach my $e (sort @array) { if ($last eq $e) { $count++; } else { print "$count\t$last\n"; $count=1; $last=$e; } } print "$count\t$last\n";

    Or you can simply use a hash:

    my %count; foreach my $e (@array) { $count{$e}++; } while (my($e,$count)=each(%count)) { print "$count\t$e\n"; }
    (both of these are untested, but should give you a good general idea).
Re: sorting arrays
by Limbic~Region (Chancellor) on May 28, 2004 at 16:25 UTC
    ucanflyit,
    Perhaps you should read the man page on uniq.
    sort file | uniq -c
    The obvious Perl solution is to use a hash an increment the key each time the item is found. If original order is important, in addition to the hash, push the value into an array unless the key already exists in the hash. You can use the array to get a hash slice in the original order.

    Cheers - L~R