Gossamer Forum
Home : General : Perl Programming :

How to use sort?

Quote Reply
How to use sort?
  I need to sort an array, but I donīt know how to do it.
I have a database with a lot of data separated by "|".
I would like to sort depending on the 10th element of this. I want from the highest
to the lowest. Can someone explain it to me?

Thanks..
Quote Reply
Re: How to use sort? In reply to
Use DBMAN...It has nice sorting options.

------------------
Eliot Lee
Founder and Editor
Anthro TECH, L.L.C
http://www.anthrotech.com/
info@anthrotech.com
==========================
Coconino Community College
http://www.coco.cc.az.us/
Web Technology
Coordinator
elee@coco.cc.az.us
Quote Reply
Re: How to use sort? In reply to
Ok, but can you explain the code itself to me?
In the dbman cgi is too complicated to me...
Quote Reply
Re: How to use sort? In reply to
I would also like to know the basics of sorting.

Anybody?

------------------
The Flying Cranes, Inc:
http://www.theflyingcranes.com
Perl scripts & Web promotion:
http://find.virtualave.net
Quote Reply
Re: How to use sort? In reply to
Here is what perldoc says about the sort command:

Code:
sort SUBNAME LIST
sort BLOCK LIST
sort LIST
Sorts the LIST and returns the sorted list value. If
SUBNAME or BLOCK is omitted, `sort()'s in standard
string comparison order. If SUBNAME is specified, it
gives the name of a subroutine that returns an integer
less than, equal to, or greater than `0', depending on
how the elements of the array are to be ordered. (The
`<=>' and `cmp' operators are extremely useful in such
routines.) SUBNAME may be a scalar variable name
(unsubscripted), in which case the value provides the
name of (or a reference to) the actual subroutine to
use. In place of a SUBNAME, you can provide a BLOCK as
an anonymous, in-line sort subroutine.

In the interests of efficiency the normal calling code
for subroutines is bypassed, with the following effects:
the subroutine may not be a recursive subroutine, and
the two elements to be compared are passed into the
subroutine not via `@_' but as the package global
variables `$a' and `$b' (see example below). They are
passed by reference, so don't modify `$a' and `$b'. And
don't try to declare them as lexicals either.

You also cannot exit out of the sort block or subroutine
using any of the loop control operators described in the
perlsyn manpage or with `goto()'.

When `use locale' is in effect, `sort LIST' sorts LIST
according to the current collation locale. See the
perllocale manpage.

Examples:

# sort lexically
@articles = sort @files;

# same thing, but with explicit sort routine
@articles = sort {$a cmp $b} @files;

# now case-insensitively
@articles = sort {uc($a) cmp uc($b)} @files;

# same thing in reversed order
@articles = sort {$b cmp $a} @files;

# sort numerically ascending
@articles = sort {$a <=> $b} @files;

# sort numerically descending
@articles = sort {$b <=> $a} @files;

# sort using explicit subroutine name
sub byage {
$age{$a} <=> $age{$b}; # presuming numeric
}
@sortedclass = sort byage @class;

# this sorts the %age hash by value instead of key
# using an in-line function
@eldest = sort { $age{$b} <=> $age{$a} } keys %age;

sub backwards { $b cmp $a; }
@harry = ('dog','cat','x','Cain','Abel');
@george = ('gone','chased','yz','Punished','Axed');
print sort @harry;
# prints AbelCaincatdogx
print sort backwards @harry;
# prints xdogcatCainAbel
print sort @george, 'to', @harry;
# prints AbelAxedCainPunishedcatchaseddoggonetoxyz

# inefficiently sort by descending numeric compare using
# the first integer after the first = sign, or the
# whole record case-insensitively otherwise

@new = sort {
($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
&#0124; &#0124;
uc($a) cmp uc($b)
} @old;

# same thing, but much more efficiently;
# we'll build auxiliary indices instead
# for speed
@nums = @caps = ();
for (@old) {
push @nums, /=(\d+)/;
push @caps, uc($_);
}

@new = @old[ sort {
$nums[$b] <=> $nums[$a]
&#0124; &#0124;
$caps[$a] cmp $caps[$b]
} 0..$#old
];

# same thing using a Schwartzian Transform (no temps)
@new = map { $_->[0] }
sort { $b->[1] <=> $a->[1]
&#0124; &#0124;
$a->[2] cmp $b->[2]
} map { [$_, /=(\d+)/, uc($_)] } @old;

If you're using strict, you *MUST NOT* declare `$a' and
`$b' as lexicals. They are package globals. That means
if you're in the `main' package, it's

@articles = sort {$main::b <=> $main::a} @files;

or just

@articles = sort {$::b <=> $::a} @files;

but if you're in the `FooPack' package, it's

@articles = sort {$FooPack::b <=> $FooPack::a} @files;

The comparison function is required to behave. If it
returns inconsistent results (sometimes saying `$x[1]'
is less than `$x[2]' and sometimes saying the opposite,
for example) the results are not well-defined.

I hope this is helpful.
Quote Reply
Re: [Bobsie] How to use sort? In reply to
I'm sure the simple answer is in this forum somewhere, but I just can't find it. I'm trying to sort an array of records (ID LastName FirstName City) by field number 2 (LastName). Will the code below, provided by Bobsie, work? And how do I reference '$age' to my field 'Lastname'?

Quote:
# sort using explicit subroutine name
sub byage {
$age{$a} <=> $age{$b}; # presuming numeric
}
@sortedclass = sort byage @class;

Thanks!

Jeff