Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在perl中对目录进行排序,考虑数字_Perl_Sorting_Readdir - Fatal编程技术网

在perl中对目录进行排序,考虑数字

在perl中对目录进行排序,考虑数字,perl,sorting,readdir,Perl,Sorting,Readdir,我想我需要某种方法来让它工作,但我很难弄清楚,因为perl不是我最强大的语言 我有一个目录,其内容如下: album1.htm album2.htm album3.htm .... album99.htm album100.htm 我正试图从这个目录(在本例中为album100.htm)获取编号最高的相册。请注意,文件上的时间戳不是确定事情的可靠方法,因为人们在事后添加旧的“缺失”相册 以前的开发人员只是使用了下面的代码片段,但一旦一个目录中有9个以上的相册,显然就会出现故障 opendir(

我想我需要某种方法来让它工作,但我很难弄清楚,因为perl不是我最强大的语言

我有一个目录,其内容如下:

album1.htm
album2.htm
album3.htm
....
album99.htm
album100.htm
我正试图从这个目录(在本例中为album100.htm)获取编号最高的相册。请注意,文件上的时间戳不是确定事情的可靠方法,因为人们在事后添加旧的“缺失”相册

以前的开发人员只是使用了下面的代码片段,但一旦一个目录中有9个以上的相册,显然就会出现故障

opendir(DIR, PATH) || print $!;
@files = readdir(DIR);
foreach $file ( sort(@files) ) {
    if ( $file =~ /album/ ) {
        $last_file = $file;
    }
}

如果你只需要找到编号最高的唱片集,你不需要对列表进行排序,只需浏览列表并跟踪最大编号即可

#!/usr/bin/perl 

use strict;
use warnings;

my $max = 0;

while ( <DATA> ) {
    my ($album) = $_ =~ m/album(\d+)/;
    $max = $album if $album > $max;
}

print "album$max.htm";

__DATA__
album1.htm
album100.htm
album2.htm
album3.htm
album99.htm
#/usr/bin/perl
严格使用;
使用警告;
我的$max=0;
而(){
我的($album)=$\u=~ m/album(\d+)/;
$max=$album,如果$album>$max;
}
打印“相册$max.htm”;
__资料__
相册1.htm
相册100.htm
相册2.htm
相册3.htm
相册99.htm

如果您只需要找到编号最高的唱片集,您实际上不需要对列表进行排序,只需运行列表并跟踪最大值即可

#!/usr/bin/perl 

use strict;
use warnings;

my $max = 0;

while ( <DATA> ) {
    my ($album) = $_ =~ m/album(\d+)/;
    $max = $album if $album > $max;
}

print "album$max.htm";

__DATA__
album1.htm
album100.htm
album2.htm
album3.htm
album99.htm
#/usr/bin/perl
严格使用;
使用警告;
我的$max=0;
而(){
我的($album)=$\u=~ m/album(\d+)/;
$max=$album,如果$album>$max;
}
打印“相册$max.htm”;
__资料__
相册1.htm
相册100.htm
相册2.htm
相册3.htm
相册99.htm

要查找最大的数字,请尝试自定义排序

sub sort_files {
    (my $num_a = $a) =~ s/^album(\d+)\.htm$/$1/;
    (my $num_b = $b) =~ s/^album(\d+)\.htm$/$1/;
    return $num_a <=> $num_b;
}

my @sorted = sort \&sort_files @files;
my $last = pop @sorted;
子排序\u文件{
(我的$num_a=$a)=~s/^album(\d+)\.htm$/$1/;
(我的$num_b=$b)=~s/^album(\d+)\.htm$/$1/;
返回$num_a$num_b;
}
我的@sorted=sort\&sort_files@files;
my$last=pop@sorted;

另外,请看一下模块。它将让你只挑选以“album”开头的文件。我发现它比readdir要简单一些。

要找到最大的数字,请尝试自定义排序

sub sort_files {
    (my $num_a = $a) =~ s/^album(\d+)\.htm$/$1/;
    (my $num_b = $b) =~ s/^album(\d+)\.htm$/$1/;
    return $num_a <=> $num_b;
}

my @sorted = sort \&sort_files @files;
my $last = pop @sorted;
子排序\u文件{
(我的$num_a=$a)=~s/^album(\d+)\.htm$/$1/;
(我的$num_b=$b)=~s/^album(\d+)\.htm$/$1/;
返回$num_a$num_b;
}
我的@sorted=sort\&sort_files@files;
my$last=pop@sorted;

另外,请看一下模块。它将让你只挑选以“album”开头的文件。我发现它比readdir要简单一些。

遇到困难的原因是运算符,
是数字比较,
cmp
是默认值,是字符串比较

$ perl -E'say for sort qw/01 1 02 200/';
01
02
1
200
稍加修改,我们就更接近正确:

$ perl -E'say for sort { $a <=> $b } qw/01 1 02 200/';
01
1
02
200

它很酷,因为它既紧凑又高效。

遇到困难的原因是运算符,
是数字比较,
cmp
是默认值,是字符串比较

$ perl -E'say for sort qw/01 1 02 200/';
01
02
1
200
稍加修改,我们就更接近正确:

$ perl -E'say for sort { $a <=> $b } qw/01 1 02 200/';
01
1
02
200

它很酷,因为它既紧凑又高效。

在这里,使用Schwartzian变换:

my @files = <DATA>;

print join '',
    map  { $_->[1] }
    sort { $a->[0] <=> $b->[0] }
    map  { [ m/album(\d+)/, $_ ] }
    @files;


 __DATA__
album12.htm
album1.htm
album2.htm
album10.htm
my@files=;
打印联接“”,
映射{$\->[1]}
排序{$a->[0]$b->[0]}
映射{[m/album(\d+/,$]}
@档案;
__资料__
相册12.htm
相册1.htm
相册2.htm
相册10.htm

在这里,使用Schwartzian变换:

my @files = <DATA>;

print join '',
    map  { $_->[1] }
    sort { $a->[0] <=> $b->[0] }
    map  { [ m/album(\d+)/, $_ ] }
    @files;


 __DATA__
album12.htm
album1.htm
album2.htm
album10.htm
my@files=;
打印联接“”,
映射{$\->[1]}
排序{$a->[0]$b->[0]}
映射{[m/album(\d+/,$]}
@档案;
__资料__
相册12.htm
相册1.htm
相册2.htm
相册10.htm

这里有一个替代解决方案,使用:

使用严格;
使用警告;
使用列表::Util'reduce';
我的$max=减少{
我的($aval,$bval)=($a=~m/专辑(\d+)/,$b=~m/专辑(\d+)/);
$aval>$bval?$a:$b
} ;
打印“最大相册为$max\n”;
__资料__
相册1.htm
相册100.htm
相册2.htm
相册3.htm
相册99.htm

这里有一个替代解决方案,使用:

使用严格;
使用警告;
使用列表::Util'reduce';
我的$max=减少{
我的($aval,$bval)=($a=~m/专辑(\d+)/,$b=~m/专辑(\d+)/);
$aval>$bval?$a:$b
} ;
打印“最大相册为$max\n”;
__资料__
相册1.htm
相册100.htm
相册2.htm
相册3.htm
相册99.htm

这里有一个通用的解决方案:

my @sorted_list
    = map  { $_->[0] } # we stored it at the head of the list, so we can pull it out
      sort {
          # first test a normalized version
          my $v = $a->[1] cmp $b->[1];
          return $v if $v;

          my $lim = @$a > @$b ? @$a : @$b;

          # we alternate between ascii sections and numeric
          for ( my $i = 2; $i < $lim; $i++ ) {
              $v  =  ( $a->[$i] || '' ) cmp ( $b->[$i] || '' );
              return $v if $v;

              $i++;
              $v = ( $a->[$i] || 0 ) <=> ( $b->[$i] || 0 );
              return $v if $v;
          }
          return 0;

      }
      map {
          # split on digits and retain captures in place.
          my @parts = split /(\d+)/;
          my $nstr  = join( '', map { m/\D/ ? $_ : '0' x length() } @parts );
          [ $_, $nstr, @parts ];
      } @directory_names
      ;
my@sorted\u列表
=map{$\u->[0]}我们将它存储在列表的最前面,因此可以将其拉出
分类{
#首先测试规范化版本
my$v=$a->[1]cmp$b->[1];
如果$v,则返回$v;
我的$lim=@$a>@$b?@$a:@$b;
#我们交替使用ascii部分和数字部分
对于(我的$i=2;$i<$lim;$i++){
$v=($a->[$i]|| |'')cmp($b->[$i]| |'');
如果$v,则返回$v;
$i++;
$v=($a->[$i]| | 0)($b->[$i]| | 0);
如果$v,则返回$v;
}
返回0;
}
地图{
#按数字分割并将捕获保留在适当位置。
my@parts=split/(\d+)/;
my$nstr=join(“”,映射{m/\D/?$\:'0'x length()}@parts);
[$\$nstr,@parts];
}@directory\u名称
;

这里有一个通用的解决方案:

my @sorted_list
    = map  { $_->[0] } # we stored it at the head of the list, so we can pull it out
      sort {
          # first test a normalized version
          my $v = $a->[1] cmp $b->[1];
          return $v if $v;

          my $lim = @$a > @$b ? @$a : @$b;

          # we alternate between ascii sections and numeric
          for ( my $i = 2; $i < $lim; $i++ ) {
              $v  =  ( $a->[$i] || '' ) cmp ( $b->[$i] || '' );
              return $v if $v;

              $i++;
              $v = ( $a->[$i] || 0 ) <=> ( $b->[$i] || 0 );
              return $v if $v;
          }
          return 0;

      }
      map {
          # split on digits and retain captures in place.
          my @parts = split /(\d+)/;
          my $nstr  = join( '', map { m/\D/ ? $_ : '0' x length() } @parts );
          [ $_, $nstr, @parts ];
      } @directory_names
      ;
my@sorted\u列表
=map{$\u->[0]}我们将它存储在列表的最前面,因此可以将其拉出
分类{
#首先测试规范化版本
my$v=$a->[1]cmp$b->[1];
如果$v,则返回$v;
我的$lim=@$a>@$b?@$a:@$b;
#我们交替使用ascii部分和数字部分
对于(我的$i=2;$i<$lim;$i++){
$v=($a->[$i]|| |'')cmp($b->[$i]| |'');
如果$v,则返回$v;
$i++;
$v=($a->[$i]| | 0)($b->[$i]| | 0);
如果$v,则返回$v;
}
返回0;
}
地图{
#按数字分割并将捕获保留在适当位置。
my@parts=split/(\d+)/;
my$nstr=join(“”,映射{m/\D/?$\:'0'x length()}@parts);
[$\$nstr,@parts];
}@directory\u名称
;