sorting file names

Discussion in 'Perl Misc' started by mixo, Dec 5, 2003.

  1. mixo

    mixo Guest

    I have file name that have a prefix "t-", which
    is followed by a number (integer), like
    t-1
    t-2
    t-3
    t-10
    t-21
    and so on.

    How can I sort this in numeric order? This avoid a situation
    where I get:
    t-1
    t-10
    t-2
    t-21
    t-3
    and so on.

    So I far have the following which suffers from the above symptom:
    ++++++++++++
    #!/usr/bin/perl -w
    opendir THISDIR, "." or die "serious dainbramage: $!";
    @allfiles = readdir THISDIR;
    @allfiles = sort @allfiles;
    #@allfiles = reverse @allfiles;


    closedir THISDIR;
    print "@allfiles\n";
    ++++++++++++
     
    mixo, Dec 5, 2003
    #1
    1. Advertising

  2. mixo

    W K Guest

    "Christian Winter" <> wrote in message
    news:3fd040f3$0$20227$-online.net...

    > But im almost 100% sure there are others here who can
    > give you more elegant solutions.


    I don't usually like to play about with "elegant" and "map" as some C
    programmer might have to look at it.
    Anyway:

    @a=qw(t-1 t-12 t-4 t-50 t-24);
    print join("\n",sort {substr($a,2)<=>substr($b,2)} @a);

    Moral of the story : you can muck about with what is in the sort {block}
     
    W K, Dec 5, 2003
    #2
    1. Advertising

  3. mixo

    Ingo Menger Guest

    mixo <> wrote in message news:<bqpdjd$86k$>...


    > @allfiles = sort @allfiles;


    @allfiles = map { "t-$_" }
    sort { $a <=> $b }
    map { s/^t-// } @allfiles;

    In english:
    Assign to @allfiles the array that results from
    prepending the string "t-" to each element of the array
    that results from a numeric sort of the array
    that results from stripping the string "t-" from each element of @allfiles

    > #@allfiles = reverse @allfiles;


    To reverse the sort, swap $a and $b in the sort sub.
     
    Ingo Menger, Dec 5, 2003
    #3
  4. mixo

    Anno Siegel Guest

    Ingo Menger <> wrote in comp.lang.perl.misc:
    > mixo <> wrote in message
    > news:<bqpdjd$86k$>...
    >
    >
    > > @allfiles = sort @allfiles;

    >
    > @allfiles = map { "t-$_" }
    > sort { $a <=> $b }
    > map { s/^t-// } @allfiles;


    Untested, eh?

    You forgot that s/// returns success or failure of the replacement, not
    the changed string. Change the last line to

    map { s/^t-//; $_ } @allfiles;

    Anno
     
    Anno Siegel, Dec 5, 2003
    #4
  5. On 5 Dec 2003, Anno Siegel wrote:

    >Ingo Menger <> wrote in comp.lang.perl.misc:
    >>
    >> @allfiles = map { "t-$_" }
    >> sort { $a <=> $b }
    >> map { s/^t-// } @allfiles;

    >
    >You forgot that s/// returns success or failure of the replacement, not
    >the changed string. Change the last line to
    >
    > map { s/^t-//; $_ } @allfiles;


    I'd use grep(). It saves the effort of having to return $_, and it makes
    more sense because this code is designed to sort those SPECIFIC files:

    @allfiles =
    map "t-$_",
    sort { $a <=> $b }
    grep s/^t-//,
    @allfiles;

    --
    Jeff Pinyan RPI Acacia Brother #734 2003 Rush Chairman
    "And I vos head of Gestapo for ten | Michael Palin (as Heinrich Bimmler)
    years. Ah! Five years! Nein! No! | in: The North Minehead Bye-Election
    Oh. Was NOT head of Gestapo AT ALL!" | (Monty Python's Flying Circus)
     
    Jeff 'japhy' Pinyan, Dec 5, 2003
    #5
  6. mixo

    Sara Guest

    mixo <> wrote in message news:<bqpdjd$86k$>...
    > I have file name that have a prefix "t-", which
    > is followed by a number (integer), like
    > t-1
    > t-2
    > t-3
    > t-10
    > t-21
    > and so on.
    >
    > How can I sort this in numeric order? This avoid a situation
    > where I get:
    > t-1
    > t-10
    > t-2
    > t-21
    > t-3
    > and so on.
    >
    > So I far have the following which suffers from the above symptom:
    > ++++++++++++
    > #!/usr/bin/perl -w
    > opendir THISDIR, "." or die "serious dainbramage: $!";
    > @allfiles = readdir THISDIR;
    > @allfiles = sort @allfiles;
    > #@allfiles = reverse @allfiles;
    >
    >
    > closedir THISDIR;
    > print "@allfiles\n";
    > ++++++++++++



    The statement

    @allfiles = sort @allfiles;

    is NOT a numeric sort. It's an alphanumeric sort. You'll need to use
    the spaceship operator to do a numeric sort <=> . However you don't
    have numbers..

    Since you APPEAR to have a constant 'T-' in front of the filenames,
    lets strip that off, sort numerically, then put it back. If its not a
    true constant, you will have to store the prefix then put it back.

    OK lets get busy. Remember, loops like for {} BAD! Let's use some Perl
    instead:

    #!/usr/bin/perl -wd

    my @a = qw(T-1 T-12 T-5 T-3 T-6);
    map s/^\D+//,@a; # stip off the prefix, don't really need the carat
    but its OK
    @a = sort { $a <=> $b } @a; # sort numerically using spaceship
    map s/^/T-/,@a; # put the prefix back on
    print "$_\n" for @a; # report success!


    DB<1> c
    T-1
    T-3
    T-5
    T-6
    T-12
    Debugged program terminated. Use q to quit or R to restart,

    Happy Holidays.
    G
     
    Sara, Dec 5, 2003
    #6
  7. mixo wrote:
    > I have file name that have a prefix "t-", which
    > is followed by a number (integer), like
    > t-1
    > t-2
    > t-3
    > t-10
    > t-21
    > and so on.
    >
    > How can I sort this in numeric order?


    Oh come on, it's not that difficult.

    > ++++++++++++
    > #!/usr/bin/perl -w
    > opendir THISDIR, "." or die "serious dainbramage: $!";
    > @allfiles = readdir THISDIR;
    > @allfiles = sort @allfiles;


    Did you read the documentation of sort()?
    It clearly says:
    [...]. If SUBNAME or
    BLOCK is omitted, "sort"s in standard string comparison order.

    And further down in the examples:
    # sort numerically ascending
    @articles = sort {$a <=> $b} @files;

    Now, obviously your file names are not numbers, so the code block needs to
    extract the number part of $a and $b before calling <=>. Because you have
    such a well-defined format you could simply use substr to remove the
    unwanted "t-":

    sort {substr($a,2)<=>substr($b,2)} @a;

    > closedir THISDIR;
    > print "@allfiles\n";
    > ++++++++++++


    jue
     
    Jürgen Exner, Dec 5, 2003
    #7
  8. mixo

    David Guest

    mixo <> wrote:

    > How can I sort this in numeric order? This avoid a situation
    > where I get:
    > t-1
    > t-10
    > t-2
    > t-21
    > t-3
    > and so on.


    Sounds like a job for Sort::Naturally, available at your local CPAN mirror.

    - David
     
    David, Dec 5, 2003
    #8
  9. mixo <> wrote in message news:<bqpdjd$86k$>...
    > I have file name that have a prefix "t-", which
    > is followed by a number (integer), like
    > t-1
    > t-2
    > t-3
    > t-10
    > t-21
    > and so on.
    >
    > How can I sort this in numeric order? This avoid a situation
    > where I get:
    > t-1
    > t-10
    > t-2
    > t-21
    > t-3
    > and so on.
    >
    > So I far have the following which suffers from the above symptom:
    > ++++++++++++
    > #!/usr/bin/perl -w
    > opendir THISDIR, "." or die "serious dainbramage: $!";
    > @allfiles = readdir THISDIR;
    > @allfiles = sort @allfiles;
    > #@allfiles = reverse @allfiles;
    >
    >
    > closedir THISDIR;
    > print "@allfiles\n";
    > ++++++++++++


    my @list = qw(t-1
    t-2
    t-3
    t-10
    t-21);

    my (@files);
    push (@files, (split/-/, $_)[1]) for (@list);

    for (sort {$a <=> $b } @files) {
    print "t-$_\n";
    # do appropriate processing
    }

    HTH

    jimk
     
    James E Keenan, Dec 5, 2003
    #9
  10. mixo <> wrote in message news:<bqpdjd$86k$>...
    > I have file name that have a prefix "t-", which
    > is followed by a number (integer), like
    > t-1
    > t-2
    > t-3
    > t-10
    > t-21
    > and so on.
    >
    > How can I sort this in numeric order?


    You could use the Schwartzian Transform. It is easier to follow if you
    read from the end of the expression (because this is the order of
    execution).
    Note that each file name, and the digits to sort on are placed in an
    anonymous array in the bottom map which is then passed to the sort
    line, and so forth.

    Chris

    #!/usr/bin/perl
    use strict;
    use warnings;

    my @files = qw / t-1.txt t-4.txt t-10.txt t-14.txt t-11.txt /;

    my @sorted = map {$_->[0]}
    sort {$a->[1] <=> $b->[1]}
    map { [ $_, /-(\d+)/ ] }
    @files;

    print "@sorted\n";

    __END__
    output: t-1.txt t-4.txt t-10.txt t-11.txt t-14.txt
     
    Chris Charley, Dec 5, 2003
    #10
  11. mixo

    Ingo Menger Guest

    -berlin.de (Anno Siegel) wrote in message news:<bqq363$7o8$-Berlin.DE>...

    >
    > Untested, eh?
    >


    Sure. There has to be something left as execise for the OP. :)


    > map { s/^t-//; $_ } @allfiles;


    or, better yet:

    map { substr($_, 2) } @allfiles

    or
    map { m/^t-(\d+)/ and $1 } @allfiles

    It's preferrable not to change lvalues if you don't have to.
     
    Ingo Menger, Dec 8, 2003
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Paddy McCarthy
    Replies:
    3
    Views:
    717
    Anthony J Bybell
    Sep 24, 2004
  2. Bob
    Replies:
    1
    Views:
    386
    Lucas Tam
    Jul 30, 2004
  3. Lewis G. Pringle, Jr.
    Replies:
    0
    Views:
    601
    Lewis G. Pringle, Jr.
    Sep 30, 2003
  4. fBechmann
    Replies:
    0
    Views:
    400
    fBechmann
    Jun 10, 2004
  5. Sfdesigner Sfdesigner
    Replies:
    5
    Views:
    168
    Chris Shea
    Aug 13, 2007
Loading...

Share This Page