Beefy Boxes and Bandwidth Generously Provided by pair Networks DiBona
Think about Loose Coupling
 
PerlMonks  

How do I write my own sorting routine?

( #21095=categorized question: print w/ replies, xml ) 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, );
Now to sort, we just compare the array elements as keys into the hash:
my @sorted = sort { $hash{$a} <=> $hash{$b} } @array;
Hence:
my @array = ("slow", "very fast", "fast", "very slow", "acceptable");
would sort into:
very slow, slow, acceptable, fast, very fast

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;
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' ];

Please (register and) log in if you wish to add an answer



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • 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
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others wandering the Monastery: (19)
    As of 2014-04-17 16:13 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      April first is:







      Results (453 votes), past polls