Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: sorting an array with decimal points

by Laurent_R (Canon)
on Jan 14, 2018 at 09:12 UTC ( [id://1207208]=note: print w/replies, xml ) Need Help??


in reply to sorting an array with decimal points

Hi levW,

this is a typical case for using the Schwartzian Transform (see https://en.wikipedia.org/wiki/Schwartzian_transform):

use strict; use warnings; use feature "say"; my @array = qw(Patch_11.4 Patch_1.0 Patch_2.0 Patch_3.1 Patch_5.0 Patc +h_4.2 Patch_6.0 Patch_11.0 Patch_7.0 Patch_8.0 Patch_9.3 Patch_10.2 Pat +ch_11.2); @array = map { $_->[0] } sort { $a->[1] <=> $b->[1] or $a->[2] <=> $b->[2] } map { /Patch_(\d+)\.(\d+)/; [$_, $1, $2] } @array; say for @array;
The map on the last line creates an anonymous array in which the items are array refs containing the whole string, the first number and the second number (for example: [Patch_11.4, 11, 4]). The items are then sorted according to the first number and then according to the second number. At the end, the map on the first line retrieves the original strings from the sorted array refs.

Output:

$ perl sort_versions.pl Patch_1.0 Patch_2.0 Patch_3.1 Patch_4.2 Patch_5.0 Patch_6.0 Patch_7.0 Patch_8.0 Patch_9.3 Patch_10.2 Patch_11.0 Patch_11.2 Patch_11.4

Replies are listed 'Best First'.
Re^2: sorting an array with decimal points
by kcott (Archbishop) on Jan 15, 2018 at 00:02 UTC

    G'day Laurent,

    An alternative to this could be a Guttman-Rosler Transform. In the following, I've kept the same data, in the same order; and, I retained the same basic code layout for the transform.

    #!/usr/bin/env perl -l use strict; use warnings; my @array = qw{ Patch_11.4 Patch_1.0 Patch_2.0 Patch_3.1 Patch_5.0 Patch_4.2 Patch_6.0 Patch_11.0 Patch_7.0 Patch_8.0 Patch_9.3 Patch_10.2 Patch_11.2 }; @array = map substr($_, 2), sort map pack("C2", /^Patch_(\d+)\.(\d+)/) . $_, @array; print for @array;

    The output is identical to what you show.

    Just as a side note, given the list context provided by "[ ... ]", regex captures will be evaluated in that context, and your second map would only need a single statement. Here's a quick one-liner to explain:

    $ perl -E 'my @x = qw{X1.2 X3.4}; say "@$_" for map { [ $_, /X(\d+)\.( +\d+)/ ] } @x' X1.2 1 2 X3.4 3 4

    — Ken

      Hi Ken,

      Thank you for your comment. In fact, I had briefly thought about the GRT, but did not find a nice implementation of it in that specific case, so I stuck to the more traditional ST.

      You're right about that fact that the initial map in the ST solution can be made in only one statement. Given that the ST is a bit complicated to understand for a beginner not knowing about it, I thought it would be a little clearer with two separate statements in the map, I'm no longer sure that this is really the case.

Re^2: sorting an array with decimal points
by levW (Beadle) on Jan 14, 2018 at 11:13 UTC
    thanks,will need a deeper look into this code...:)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1207208]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (6)
As of 2024-04-16 08:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found