使用perl中的格式x.x.x.x对数字进行排序
例如,假设数字的格式为:使用perl中的格式x.x.x.x对数字进行排序,perl,sorting,Perl,Sorting,例如,假设数字的格式为: 1.1.10 1.1.10.1 1.1.10.2 1.1.11 1.1.12 1.1.13 1.1.13.1 1.1.3 1.1.4 我想要的输出是: 1.1.3 1.1.4 1.1.10 1.1.10.1 1.1.10.2 1.1.11 1.1.12 1.1.13 1.1.13.1 或(无模块) 或者(没有模块,速度更快,但需要一个数组而不是一个输入列表) 在pack模板中,您可以将C更改为n或nC允许最多255个数字n允许最多65535个数字N最多允许40亿个数
1.1.10
1.1.10.1
1.1.10.2
1.1.11
1.1.12
1.1.13
1.1.13.1
1.1.3
1.1.4
我想要的输出是:
1.1.3
1.1.4
1.1.10
1.1.10.1
1.1.10.2
1.1.11
1.1.12
1.1.13
1.1.13.1
或(无模块)
或者(没有模块,速度更快,但需要一个数组而不是一个输入列表)
在pack
模板中,您可以将C
更改为n
或n
<代码>C允许最多255个数字<代码>n允许最多65535个数字<代码>N最多允许40亿个数字。请尝试以下操作:
use Modern::Perl;
use Sort::Naturally qw{nsort};
my @numbers = nsort(qw{1.1.10 1.1.10.1 1.1.10.2 1.1.11 1.1.12 1.1.13 1.1.13.1 1.1.3});
say for @numbers;
输出:
1.1.3
1.1.10
1.1.10.1
1.1.10.2
1.1.11
1.1.12
1.1.13
1.1.13.1
希望这有帮助 您可能更容易理解:
sub min { $_[0] <= $_[1] ? $_[0] : $_[1] }
sub comp
{
($a1,$a2) = @_;
@a1 = @{$a1};
@a2 = @{$a2};
for (0..min(scalar @a1,scalar @a2))
{
return 1 if $a1[$_] > $a2[$_];
return -1 if $a2[$_] > $a1[$_]; #exit early if an inequality is found
}
return 0 if @a1 == @a2; #both array are equal, thus both numbers are equal
return @a1 > @a2 ? 1 : -1; #arrays are equal upto a certain point, thus longer array is 'greater'
}
@sourcearray = ('1.1.10','1.1.10.1','1.1.10.2','1.1.11','1.1.12','1.1.13','1.1.13.1','1.1.3','1.1.4');
@individual = map { [split /\./] } @sourcearray; #splits each number into arrays consisting of individual numbers
@sorted = sort {comp($a,$b)} @individual; #sort algo decides which of these two arrays are 'greater'
{
local $" = ".";
print "@{$sorted[$_]}\n" for 0..$#sorted;
}
sub-min{$\[0]$a2[$\];
如果$a2[$\u]>$a1[$\u];#如果发现不平等,则提前退出,返回-1
}
如果@a1==@a2,则返回0#两个数组相等,因此两个数相等
返回@a1>@a2?1 : -1; #数组在某一点上相等,因此数组越长“越大”
}
@sourcearray=('1.1.10'、'1.1.10.1'、'1.1.10.2'、'1.1.11'、'1.1.12'、'1.1.13'、'1.1.13.1'、'1.1.3'、'1.1.4');
@单个=映射{[split/\./]}@sourcearray#将每个数字拆分为由单个数字组成的数组
@排序=排序{comp($a,$b)}@individual#排序算法决定这两个数组中哪一个“更大”
{
本地$“=”;
打印“@{$sorted[$\]}\n”表示0..$#已排序;
}
Duplicates:6917314的副本。艾德夫的字符串没有精确的4个部分,他也没有说它们被限制在255个。快速破解:sort{eval$a cmp eval$b}@numbers
@Cupidvogel,1.1.1.10
与v1.1.1.10
相同,它将字符串化为chr(1).chr(1).chr(10)
。换句话说,eval“1.1.1.10”
是一种昂贵且危险的方法,可以将我的解决方案中的包模板中的“C
”更改为“W
“.在32位机器上,数字是否达到40亿,在64位机器上是否达到2**64-1”。@Cupidvogel在那里的评论中,tchrist详细阐述了这个特殊的“技巧”。基本上它是按照ikegami所说的,它将准数字字符串转换成一个合适的字符串,然后我们可以“安全地”使用cmp
操作符。我将其命名为快速破解,因为这可能不是解决此特定问题的好方法。无法了解排序在获取pack(…)数据时的工作方式,在本例中,pack仅从每个版本号中创建一个八位字节值。。。不是将每个数字与“cmp”进行比较也会这样做吗?@soulSurfer2010,“1.2.1”cmp“1.16.1”
失败,因为这些数字的宽度可变。使用pack C
,使它们的宽度相同。它归结为“\x01\x02\x01”cmp“\x01\x10\x01”
,由于添加了填充,因此排序正确。
use Modern::Perl;
use Sort::Naturally qw{nsort};
my @numbers = nsort(qw{1.1.10 1.1.10.1 1.1.10.2 1.1.11 1.1.12 1.1.13 1.1.13.1 1.1.3});
say for @numbers;
1.1.3
1.1.10
1.1.10.1
1.1.10.2
1.1.11
1.1.12
1.1.13
1.1.13.1
sub min { $_[0] <= $_[1] ? $_[0] : $_[1] }
sub comp
{
($a1,$a2) = @_;
@a1 = @{$a1};
@a2 = @{$a2};
for (0..min(scalar @a1,scalar @a2))
{
return 1 if $a1[$_] > $a2[$_];
return -1 if $a2[$_] > $a1[$_]; #exit early if an inequality is found
}
return 0 if @a1 == @a2; #both array are equal, thus both numbers are equal
return @a1 > @a2 ? 1 : -1; #arrays are equal upto a certain point, thus longer array is 'greater'
}
@sourcearray = ('1.1.10','1.1.10.1','1.1.10.2','1.1.11','1.1.12','1.1.13','1.1.13.1','1.1.3','1.1.4');
@individual = map { [split /\./] } @sourcearray; #splits each number into arrays consisting of individual numbers
@sorted = sort {comp($a,$b)} @individual; #sort algo decides which of these two arrays are 'greater'
{
local $" = ".";
print "@{$sorted[$_]}\n" for 0..$#sorted;
}