kepler has asked for the wisdom of the Perl Monks concerning the following question:

Greetings

I'm having some troubles to place in order some files I have in an array. Its format is of the type "name(p or m)xxxx.xxx", that is, begins with "name", then with 'p' or 'm' (meaning + or -), then 4 digits (from 0000 to 9999), and then extension is the same for all (3 digits). So a logic sequence would be namem1100.111.namem0900.111, namem0010.111, namep0000.111, namep0800.111, namep9999.111. Is there a quick way to order the array with these rules? I'm not an expert in these kind or orders...

Kind regards

Kepler

Replies are listed 'Best First'.
Re: Aid for regex expression
by tybalt89 (Monsignor) on Dec 29, 2017 at 19:15 UTC
    #!/usr/bin/perl # http://perlmonks.org/?node_id=1206433 use strict; use warnings; use List::Util 'shuffle'; use Data::Dump 'pp'; my @before = shuffle qw( namem1100.111 namem0900.111 namem0010.111 namep0000.111 namep0800.111 namep9999.111 ); pp \@before; my @after = sort { $a =~ s/.*([pm]\d+).*/$1/r =~ tr/pm/+-/r <=> $b =~ s/.*([pm]\d+).*/$1/r =~ tr/pm/+-/r } @before; pp \@after;

    Outputs:

    [ "namem0900.111", "namep9999.111", "namem1100.111", "namep0800.111", "namep0000.111", "namem0010.111", ] [ "namem1100.111", "namem0900.111", "namem0010.111", "namep0000.111", "namep0800.111", "namep9999.111", ]
      Brilliant... :) Thanks.
Re: Aid for regex expression
by Your Mother (Archbishop) on Dec 29, 2017 at 19:22 UTC

    This is probably not helpful but it is fun. :P

    use strictures; use List::Util "shuffle"; # Randomize the order my @stuf = shuffle qw( namem1100.111 namem0900.111 namem0010.111 namep +0000.111 namep0800.111 namep9999.111 ); print join("\n", "Before-", @stuf), $/; # Update: didn't mean to leave this -> no warnings "uninitialized"; @stuf = map $_->[0], sort { $a->[3] <=> $b->[3] } map { /name([mp])(\d{4}\.\d{3})/; [ $_, $1, $2, $1 eq "m" ? (0-$2) : (0+$2) ] } @stuf; print join("\n", "After-", @stuf), $/;

    See Schwartzian Transform and https://en.wikipedia.org/wiki/Schwartzian_transform.

Re: Aid for regex expression
by 1nickt (Canon) on Dec 29, 2017 at 19:27 UTC

    See sort for how to create a custom sort routine.

    Your spec is not clear but here I am assuming:

    1. sort first by ascending m or p
    2. sort next by ascending last four digits of file name before extension
    3. sort last by the "name" in ascending alphabetical order
    4. the "name" portion will be arbitrary

    So, use substr and work from the end, since you don't know know how many characters are in the "name", but you do know for the extension and the four-digit numeric part.

    Here I sorted the lines manually as described, for the source. Then rearranged them, sorted them with the custom subroutine, and used Test::More to check the results. I also added a couple of entries to show the final sort criterion.

    use strict; use warnings; use Test::More tests => 1; use List::Util 'shuffle'; chomp( my @lines = <DATA> ); my @shuffled = shuffle @lines; my @sorted = sort my_sort @shuffled; is "@sorted", "@lines", 'same order'; sub my_sort { substr( $a, -9, 1 ) cmp substr( $b, -9, 1 ) || substr( $a, -8, 4 ) <=> substr( $b, -8, 4 ) || substr( $a, 0, (length $a) - 8 ) cmp substr( $b, 0, (length $b) - +8 ) } __END__ Barneym0010.111 Fredm0010.111 namem0010.111 namem0900.111 namem1100.111 namep0000.111 namep0800.111 namep9999.111
    Output:
    $ perl 1206433.pl 1..1 ok 1 - same order

    Update: Added sorting by "name" after realizing the files are probably not actually named "name*" :-P

    Hope this helps!


    The way forward always starts with a minimal test.