Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I sort a list of strings by numbers in them?

An easy one no doubt for you...

I have a list of filenames which are like so;

fw_d.log.1.gz  
through  
fw_d.log.300.gz  

When i use this below code block, it almost sorts it the way i want, but not quite.

#!/usr/bin/perl -w
my $basedir = "/var/log";
my @verdir = qw(fw_d);
my $fulldir;
my $configs;
my $combidir;

foreach $combidir (@verdir) {
    $fulldir = "$basedir/$combidir";
    opendir (DIR, $fulldir);
    my @files = grep { $_ ne '.' && $_ ne '..' && $_ ne 'CVS' readdir DIR;
    closedir (DIR);
    @files1 = sort {$a cmp $b}(@files);
    foreach my $configs (@files1) {
        print "Checking $configs\n";
        system("less $basedir/$combidir/$configs | grep \'.* Group = , Username = .* autheauthenticated.\' >> output.log" );
    }
}

here is a snippet output

Checking fw_d.log  
Checking fw_d.log.1.gz  
Checking fw_d.log.10.gz  
Checking fw_d.log.100.gz  
Checking fw_d.log.101.gz  
Checking fw_d.log.102.gz  

As you can see, it almost sorts it how i was hoping.... Does anyone have any suggestions, on either reading, or a code snippet i can use?

Thanks in advance.
Steve.

like image 808
Steve Avatar asked Jun 08 '11 17:06

Steve


People also ask

How do you sort a list of strings containing numbers in Python?

By default, sorting is done in ascending order. If you want to sort in descending order, set the reverse parameter to True . The example uses sorted() , but you can also use sort() . For more information, including how to sort tuples and strings, see the following article.

Can you sort a list of strings?

sort() list provides a member function sort(). It Sorts the elements of list in low to high order i.e. if list is of numbers then by default they will be sorted in increasing order. Whereas, if list is of strings then, it will sort them in alphabetical order.

How do I sort strings that contain numbers in Java?

Core Java bootcamp program with Hands on practice Get the String. Create an empty integer array. The split() method of the string class accepts a string representing a delimiter, splits the current string into an array of tokens. Using this method split the given string into an array of tokens.


1 Answers

You could use Schartzian-transform :

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

Added benchmark for comparison between Schwartzian-Transform and subroutine

use Benchmark qw(:all);

# build list of files
my @files = map {'fw_d.log.'.int(rand()*1000).'.log' } 0 ..300;

my $count = -3;
my $r = cmpthese($count, {
        'subname' => sub {
              sub expand {
                   my $file=shift; 
                   $file=~s{(\d+)}{sprintf "%04d", $1}eg;
                   return $file;
              }
              my @sorted = sort { expand($a) cmp expand($b) } @files;
        },
        'schwartzian' => sub {
              my @sorted = map  { $_->[0] }
                           sort { $a->[1] <=> $b->[1] }
                           map  { [$_, $_=~/(\d+)/] }
                 @files;
         }
});

Result:

              Rate     subname schwartzian
subname     21.2/s          --        -92%
schwartzian  279/s       1215%          --

Schwartzian-transform is about 13 times more efficient for sorting 300 files.

like image 85
Toto Avatar answered Oct 15 '22 03:10

Toto