Re: Sorting in PERL

by "Bill Pierson" <wpierson(at)tampabay.rr.com>

 Date:  Tue, 5 Sep 2000 15:09:35 -0400
 To:  "Administrator" <sowinso(at)sowinso.com>
 Cc:  <hwg-languages(at)hwg.org>
 References:  icehouse
  todo: View Thread, Original
Thanks for the information.

I actually found an outstanding routine for sorting from a hwg member.... It
took some research, but for those who also had a PERL sort quandry with the
same circumstances that I was facing, here is an outstanding solution:

(This is from http://www.effectiveperl.com/recipes/sorting.html :)

Lets say we have an array, @data, and it's delimited by commas.
$data[0] = "bananas,apples,oranges,grapes";
$data[1] = "pants,shoes,shorts,glasses";

Command:
@sorted = fieldsort('\,', ['-1n'], @data);

@sorted = fieldsort('delmiter', [string/numeric operator], @array);
delimter is what the array is delimited with, in this case commas. A \ is
used for the literal use of the comma.....
string/numeric operator is the field position that you'd like sorted. If
it's a negative number, it sorts ascending, positive number sorts
descending. If there is an n appended, it sorts numerically, no n sorts
asciibetically.

If I were to apply the subroutine fieldsort with \., (comma delimited) and 1
as the operator, it would compare bananas and pants asciibetically, and sort
them descending. If I were to apply it with -2 as the operator, it would
compare apples and shoes and sort them ascending.

There are ways to layer the sorting, (ie sort by last name, then by birth
date, etc.) as described in the link above.

sub fieldsort {
    my ($sep, $cols);
    if (ref $_[0]) {
        $sep = '\\s+'
    } else {
        $sep = shift;
    }
    unless (ref($cols = shift) eq 'ARRAY') {
        die "fieldsort columns must be in anon array";
    }
    my (@sortcode, @col);
    my $col = 1;
    for (@$cols) {
        my ($a, $b) = /^-/ ? qw(b a) : qw(a b);
        my $op = /n$/ ? '<=>' : 'cmp';
        push @col, (/(\d+)/)[0] - 1;
        push @sortcode, "\$${a}->[$col] $op \$${b}->[$col]";
        $col++;
    }
    my $sortfunc = eval "sub { " . join (" or ", @sortcode) . " } ";
    my $splitfunc = eval 'sub { (split /$sep/o, $_)[@col] } ';
    return
        map $_->[0],
        sort { $sortfunc->() }
        map [$_, $splitfunc->($_)],
        @_;
}


Thanks for your help, and I hope this helps as well.
--Bill


----- Original Message -----
From: "Administrator" <sowinso(at)sowinso.com>
To: "'Bill Pierson'" <wpierson(at)tampabay.rr.com>; <hwg-languages(at)hwg.org>
Sent: Tuesday, September 05, 2000 1:17 PM
Subject: RE: Sorting in PERL


Bill,

You're going to have to use the sort and split functions.  You'll have to
check this on your own, and add error checking.  I'm on vacation, and
therefore not in the office, so I'm forced to help you from memory.  I have
no idea whether this will work or not.  *shrug*  Also, if you don't know the
type of the fields beforehand, you will have to write a routine which
figures it out.

Who knows...it might not work at all!

#this is the actual sorting routine, it will be called by the main routine
sub sort_string
{
($field_number) = @_;
@a_fields = split /,/, $a, $field_number+2;
@b_fields = split /,/, $b, $field_number+2;
return $a_fields($field_number) cmp $b_fields($field_number);
}
sub sort_numeric
{
($field_number) = @_;
@a_fields = split /,/, $a, $field_number+2;
@b_fields = split /,/, $b, $field_number+2;
return $a_fields($field_number) <=> $b_fields($field_number);
}

#a couple of unusual definitions
$a_string = 1;
$a_number = 0;

#hopefully we know what kind of data is in each field, if not, we have to
detect it somehow and construct this array
@field_type = ($a_string, $a_string, $a_number);

#this next line will probably not be in your script, but it must be
determined by now
$field_no = 0;

# now sort
if ($field_type($field_no))
{
@sorted = sort {&sort_string($field_no)} @line;
}
else
{
@sorted = sort {&sort_numeric($field_no)} @line;
}


Good luck,
Brian A. Sayrs
Owner, Southwind Solutions


-----Original Message-----
From: Bill Pierson [SMTP:wpierson(at)tampabay.rr.com]
Sent: Friday, September 01, 2000 6:30 AM
To: hwg-languages(at)hwg.org
Subject: Sorting in PERL

Greetings all,
I've had some difficulty figuring out this whole PERL sorting thing. I'd
like to be able to sort by parts of an array, if possible.

For example:
$line[0] = "Arthur,Johnson,53";
$line[1] = "Bob,Franklin,12";

If I wanted to sort by the first field, First Name, is it possible?
If I wanted to sort by the third field, Age, how would I do that?


Any information would be appreciated.
Thanks,
--Bill

HWG: hwg-languages mailing list archives, maintained by Webmasters @ IWA