Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

How do you specify which fields to sort by when sorting an array.

by brentheigold (Novice)
on Jul 14, 2002 at 22:39 UTC ( #181658=perlquestion: print w/ replies, xml ) Need Help??
brentheigold has asked for the wisdom of the Perl Monks concerning the following question:

Say for example I had an array that I created by reading in a file, so:
while ( <INPUT_FILE>) { my ($name, $id, $address, $phone) = split(','); push(@outputRef, $name, $id, $address, $phone); }
Then if I wanted to do an ascending sort on the @outputRef array ONLY BY name and phone number, how would I do that? I would really appreciate help on this, if you know how to do this then thanks a lot in advance. Brent.

Replies are listed 'Best First'.
Re: How do you specify which fields to sort by when sorting an array.
by chromatic (Archbishop) on Jul 14, 2002 at 22:51 UTC
    There are several examples given in the documentation for sort. The trick is specifying which fields of $a and $b to compare:
    my @output; while (<INPUT_FILE>) { push @output, [ split(',', $_, 4) ]; } my @sorted = sort { $a->[0] cmp $b->[0] || $a->[3] <=> $b->[3] } @output;
    I took the liberty of fixing the name of @outputRef (which is not a reference) and pushing each row as an anonymous array. I also use numeric comparisons on the phone numbers.
Re: How do you specify which fields to sort by when sorting an array.
by tadman (Prior) on Jul 15, 2002 at 04:37 UTC
    I'm not sure why chromatic seemed to miss the boat on this one. Although I might be wrong, it would seem that the linefeed ("\n") is being left on the fourth element of the array. Maybe a rushed posting. Here's a more compacted version:
    my @output = sort { $a->[0] cmp $b->[0] || $a->[3] <=> $b->[3] } map { chomp; [ split(',', $_, 4) ] } <INPUT_FILE>;
    Remember that with this kind of structure the data flows from the bottom up. From the file, through the map which makes the proper array-of-arrays (AoA), and in to the sort routine which re-orders it before storing the result in @output.

    As a note, though, comparing phone numbers numerically is pretty lacking. If one has a dot and the other a dash, your sort is going to be ruined. Here's a more robust version that only sorts the numerical component of the phone number, ignoring brackets, dashes and the like:
    sub phone_value { my ($v) = @_; $v =~ tr/^0-9//d; return $v; } my @output = sort { $a->[0] cmp $b->[0] || phone_value($a->[3]) <=> phone_value($b->[3]) } map { chomp; [ split(',', $_, 4) ] } <INPUT_FILE>;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://181658]
Approved by samtregar
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (15)
As of 2016-08-26 14:46 GMT
Find Nodes?
    Voting Booth?
    The best thing I ever won in a lottery was:

    Results (372 votes). Check out past polls.