Syntactic Confectionery Delight PerlMonks

### How do I write my own sorting routine?

by Russ (Deacon)
 on Jul 05, 2000 at 12:35 UTC Need Help??
Contributed by Russ on Jul 05, 2000 at 12:35 UTC
Q&A  > sorting

#### Description:

I need to sort a list of strings which are network line speeds, like:  "115kbps", "2Mbps", "10Mbps", "T1 LINE", ...

If I do the standard (ASCIIbetical) sort, "10Mbps" would come before "115kbps", and "115kbps" would come before "2Mbps", which is clearly not the result I want.

So I need some trick to make a "priority hash" or array where I'd put the proper order of sort.

I understand how to make comparisons in the subroutine:

``` return -1;  # moves the item lower
return +1;  # goes above the previous one
return  0;  # equals

 Answer: How do I write my own sorting routine?contributed by jarich If you have a hash which specifies an ordering for values, then your sorting is much easier: ```my %hash = ( "very slow" => 1, "slow" => 2, "slowish" => 3, "medium" => 4, "acceptable" => 5, "fast" => 6, "very fast" => 7, ); [download]``` Now to sort, we just compare the array elements as keys into the hash: ```my @sorted = sort { \$hash{\$a} <=> \$hash{\$b} } @array; [download]``` Hence: ```my @array = ("slow", "very fast", "fast", "very slow", "acceptable"); [download]``` would sort into: ```very slow, slow, acceptable, fast, very fast [download]``` Answer: How do I write my own sorting routine?contributed by nardo return -1 means \$a goes before \$b, return +1 means \$b goes before \$a, return 0 means they are equal. The "spaceship operator", <=>, returns -1, 0, or 1 depending on whether the left argument is numerically less than, equal to, or greater than the right argument. Its stringwise counterpart, cmp, returns -1, 0, or 1 depending on whether the left argument is stringwise less than, equal to, or greater than the right argument. To learn more about these operators, please read perlop. To learn more about the sort function, please read perlfunc. Answer: How do I write my own sorting routine?contributed by gam3 This seems like it is begging for a schwartzian transform. ``` my %engr_scale = ( k => 10**3, m => 10**6, g => 10**9, t => 10**12, ); sub normalized_net_speed { local \$_ = lc shift; s/^T1\b/1.544 mbps/i; s/^([.0-9]+)\s*([kmgt])bps/ int( \$1 * \$engr_scale{lc \$2} ) /e; s/[^.0-9].*\$//; # kill non-numeric stuff \$_ } my @sorted = map { \$_->[0] } sort { \$a->[1] <=> \$b->[1] } map { [ \$_, normalized_net_speed(\$_) ] } @array; [download]``` Answer: How do I write my own sorting routine?contributed by poolpi ```#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use Math::BigInt lib => 'GMP'; my @speeds = ( '10Mbps', '115kbps', 'Flash', '2Mbps', 'T1 LINE', 'Shocker' ); my ( @clean_speeds, @sorted_speeds ); my \$speed_re = { 'BPS' => qr/(\d+)\s*([KMGT])BPS/, # 10MBPS 'T' => qr/T(\d)\s*\w*/, # T1 LINE }; my \$bps = Math::BigInt->new('2')->bpow(10); my \$unit = { 'BPS' => { K => \$bps->copy->bpow(0), M => \$bps->copy->bpow(1), G => \$bps->copy->bpow(2), T => \$bps->copy->bpow(3), }, # ref => http://ckp.made-it.com/t1234.html 'T' => { 1 => Math::BigInt->new('1544'), # T1 = 1544 kbps 2 => Math::BigInt->new('6312'), # T2 = 6312 kbps 3 => Math::BigInt->new('44736'), # T3 = 44736 kbps 4 => Math::BigInt->new('274760'), # T4 = 274760 kbps }, }; for (@speeds) { my \$speed = uc \$_; \$speed =~ /(?:\$speed_re->{'BPS'}|\$speed_re->{'T'})/ ? push @clean_speeds, \$speed : warn "Unmatched speed: \$speed\n"; } @sorted_speeds = sort { net_speed(\$a) <=> net_speed(\$b) } @clean_speeds; print Dumper \@sorted_speeds; sub net_speed { my \$speed = shift; if ( \$speed =~ /\$speed_re->{'BPS'}/ ) { Math::BigInt->new( \$unit->{'BPS'}->{\$2} )->bmul(\$1); } elsif ( \$speed =~ /\$speed_re->{'T'}/ ) { Math::BigInt->new( \$unit->{'T'}->{\$1} ); } } __END__ Output: ------ Unmatched speed: FLASH Unmatched speed: SHOCKER \$VAR1 = [ '115KBPS', 'T1 LINE', '2MBPS', '10MBPS' ]; [download]```

• Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
• Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
• Read Where should I post X? if you're not absolutely sure you're posting in the right place.
• Posts may use any of the Perl Monks Approved HTML tags:
a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
• You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
 For: Use: & & < < > > [ [ ] ]
• Link using PerlMonks shortcuts! What shortcuts can I use for linking?

Create A New User
Chatterbox?
 [karlgoethebier]: good morning [Corion]: [karlgoethebier]: anybody ever noticed the double bracket operator: while (<<>>) {print;}?

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (9)
As of 2017-07-21 07:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
I came, I saw, I ...

Results (319 votes). Check out past polls.