如何对数组进行排序,以便某些文件扩展名排在最前面?

rar*_*box 4 arrays perl

我有一个包含文件列表的数组.我想以一种方式对它进行排序,它会让我在数组的开头和之后的其余文件中包含.txt文件.

这就是我现在正在做的,这很好.

@files = (grep(/\.txt$/,@files),grep(!/\.txt$/,@files));
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法呢?

bri*_*foy 10

您询问了有关为多个文件扩展名执行此操作的后续评论.在那种情况下,我将建立Schwartzian变换.如果您是ST的新手,我推荐Joseph Hall在Effective Perl Programming中的解释.虽然第二版很快就会推出,但我们基本上都没有解释,所以第一版也同样出色.谷歌图书似乎只显示第一版的每页一英寸,所以你在那里运气不好.

在这个答案中,我使用加权函数来决定哪些扩展应该移到顶部.如果扩展没有明确的权重,我只是用词典方式对它进行排序.您可以通过排序来愚弄以获得您想要的订单:

@files = qw(
    buster.pdf
    mimi.xls
    roscoe.doc
    buster.txt
    mimi.txt
    roscoe.txt
    buster.rpm
    mimi.rpm
    );

my %weights = qw(
    txt 10
    rpm  9
    );

my @sorted = 
    map { $_->{name} }
    sort { 
        $b->{weight} <=> $a->{weight}
         ||
        $a->{ext}    cmp $b->{ext}
         ||
        $a cmp $b
        }
    map {
        my( $ext ) = /\.([^.]+)\z/;
            { # anonymous hash constructor
            name => $_,
            ext => $ext,
            weight => $weights{$ext} || 0,
            }
        }
    @files;

$" = "\n";
print "@sorted\n";
Run Code Online (Sandbox Code Playgroud)


bri*_*foy 5

你只需要在每个grep的前面添加一个排序:

 my @sorted =
   (
   sort( grep /\.txt\z/,   @files ),
   sort( grep ! /\.txt\z/, @files )
   );
Run Code Online (Sandbox Code Playgroud)

这里的诀窍是你正在对列表进行分区,然后独立地对每个分区进行排序.根据您的操作,这可能比尝试在一个排序操作中执行所有操作要好得多.相反,它可能并不总是更好.

还有其他各种方法可以完成这项工作,但它们并非如此简单.:)

这是我的MacBook Air与vanilla Perl 5.10.1的快速基准测试:

There are 600 files to sort
     brian:  3 wallclock secs @ 369.75/s (n=1161)
   control:  3 wallclock secs @ 1811.99/s (n=5744)
      leon:  4 wallclock secs @ 146.98/s (n=463)
   mobrule:  3 wallclock secs @ 101.57/s (n=324)
      sort:  4 wallclock secs @ 559.62/s (n=1746)
Run Code Online (Sandbox Code Playgroud)

这是脚本:

use Benchmark;

use vars qw(@files);

@files = qw(
    buster.pdf
    mimi.xls
    roscoe.doc
    buster.txt
    mimi.txt
    roscoe.txt
    ) x 100;


printf "There are %d files to sort\n", scalar @files;

sub leon {  
    my @sorted = 
        map { $_->[0] } 
        sort { $a->[1] <=> $b->[1] } 
        map { [ $_, !/\.txt$/ ] 
        } @files;
    }

sub brian {
     my @sorted =
       (
       sort( grep /\.txt\z/,   @files ),
       sort( grep ! /\.txt\z/, @files )
       );
    }

sub mobrule {
    my @sorted = 
        sort { ($b=~/\.txt\z/) <=> ($a=~/\.txt\z/)  ||  $a cmp $b } 
        @files;
    }

sub plain_sort {
    my @sorted = sort @files;
    }

sub control {
    my @sorted = @files;
    }

timethese( -3,
     {
     brian   => \&brian,
     leon    => \&leon,
     mobrule => \&mobrule,
     control => \&control,
     sort    => \&plain_sort,
     }
     );
Run Code Online (Sandbox Code Playgroud)


mob*_*mob 5

 

@sorted = sort { $b=~/\.txt$/ <=> $a=~/\.txt$/  ||  $a cmp $b } @files
Run Code Online (Sandbox Code Playgroud)

将首先放置.txt文件,然后按字典顺序排序(按字母顺序).

@sorted = sort { $b=~/\.txt$/ <=> $a=~/\.txt$/ } @files
Run Code Online (Sandbox Code Playgroud)

会先将.txt文件否则保留原来的顺序(sort稳定的,因为Perl的5.8)