使用Perl对值的子数组进行排序

使用Perl对值的子数组进行排序,perl,sorting,Perl,Sorting,我有以下阵列模式: 2个字母x数字2个字母y数字2个字母z数字等 我想对字母之间的数字进行排序,并保持字母的原样 例如: a b 3 5 7 4 d c 6 3 2 将成为 a b 3 4 5 7 c d 2 3 6 如何在Perl中实现这一点 我试图用什么来保存这些字母的索引 my %index=(); my $count =0 ; foreach (@arr ) { if($_~=/[a-zA-Z]) { $index{$_}=$count; } $count++ }

我有以下阵列模式: 2个字母x数字2个字母y数字2个字母z数字

我想对字母之间的数字进行排序,并保持字母的原样

例如:

 a b 3 5 7 4 d c 6 3 2    
将成为

 a b 3 4 5 7 c d 2 3 6
如何在Perl中实现这一点

我试图用什么来保存这些字母的索引

my %index=();
my $count =0 ;
foreach (@arr ) {

if($_~=/[a-zA-Z]) {
$index{$_}=$count;
}
$count++

}
然后尝试用拼接替换这些部分

我还尝试了以下似乎有效的方法:

my @a =qw(a b 1 3 5 3  c d 4 5 2);

my (@b,@c) =();
my $count=0;
foreach (@a) {
    if($_=~/[A-Za-z]/){
        push @b,sort @c;
        push @b,$_;
        if($count%2==0) { 
           @c=();
        }
        $count++;
    }
    else {
        push @c,$_;
    }
}

我想知道是否有一种更有效、更完美的方法来实现这一点?

一种方法是循环数组一次,将遇到的第一个数字的索引保持在一个序列中。当遇到字符(表示数字序列已结束)时,请直接在该数组切片中对数字序列进行排序

use strict;
my @arr = ('a','b',3,5,7,4,'d','c',6,3,2);

my $first = -1;
for (my $i = 0; $i < @arr; $i++) {
  if($arr[$i] =~ m/[a-z]/i) {
    next if ($first == -1);
    @arr[$first..($i-1)] = sort {$a<=>$b} @arr[$first..($i-1)];
    $first = -1;
  } elsif ($first == -1) {
    $first = $i;
  } 
}
#one last time after the loop
@arr[$first..(@arr-1)] = sort {$a<=>$b} @arr[$first..(@arr-1)] if ($first != -1);

print join(',',@arr)."\n";
使用严格;
my@arr=('a','b',3,5,7,4,'d','c',6,3,2);
我的$first=-1;
对于(我的$i=0;$i<@arr;$i++){
如果($arr[$i]=~m/[a-z]/i){
下一个if($first==-1);
@arr[$first..($i-1)]=排序{$a$b}@arr[$first..($i-1)];
$first=-1;
}elsif($first==-1){
$first=$i;
} 
}
#循环后的最后一次
@arr[$first..(@arr-1)]=排序{$a$b}@arr[$first..(@arr-1)]如果($first!=-1);
打印联接(“,”,@arr)。“\n”;

这更令人满意吗

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

my @list = ('a', 'b', '3', '5', '7', '4', 'd', 'c', '6', '3', '2');

for (my $i = 0; $i < scalar(@list); $i++)
{
    if ($list[$i] =~ m/[[:alpha:]]/)
    {
        # Assume $list[$i+1] exists and is alphabetic too!
        @list[$i..$i+1] = sort @list[$i..$i+1];
        $i++;
    }
}

print "@list\n";
我对排序行中的重复切片并不完全满意,但我不确定在使用
sort
时是否有办法避免这种情况

当然,因为它是Perl,所以有不止一种方法(TMTOWTDI),所以这两种方法也都能得到正确的答案。我不确定哪一个不那么怪异。我可能缺少一些交换两个变量的惯用方法

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

my @list = ('a', 'b', '3', '5', '7', '4', 'd', 'c', '6', '3', '2');

for (my $i = 0; $i < scalar(@list); $i++)
{
    if ($list[$i] =~ m/[[:alpha:]]/)
    {
        ($list[$i], $list[$i+1]) = ($list[$i+1], $list[$i]) if ($list[$i] gt $list[$i+1]);
        $i++;
    }
}

print "@list\n";
#/usr/bin/env perl
严格使用;
使用警告;
我的@list=('a','b','3','5','7','4','d','c','6','3','2');
对于(我的$i=0;$i<标量(@list);$i++)
{
如果($list[$i]=~m/[:alpha:][]/)
{
($list[$i],$list[$i+1])=($list[$i+1],$list[$i])如果($list[$i]gt$list[$i+1]);
$i++;
}
}
打印“@list\n”;
交换行是可怕的,因为有三个对列表元素的引用

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

my @list = ('a', 'b', '3', '5', '7', '4', 'd', 'c', '6', '3', '2');

for (my $i = 0; $i < scalar(@list); $i++)
{
    if ($list[$i] =~ m/[[:alpha:]]/)
    {
        my($x,$y) = (\$list[$i], \$list[$i+1]);
        ($$x, $$y) = ($$y, $$x) if ($$x gt $$y);
        $i++;
    }
}

print "@list\n";
#/usr/bin/env perl
严格使用;
使用警告;
我的@list=('a','b','3','5','7','4','d','c','6','3','2');
对于(我的$i=0;$i<标量(@list);$i++)
{
如果($list[$i]=~m/[:alpha:][]/)
{
我的($x,$y)=(\$list[$i],\$list[$i+1]);
($$x,$$y)=($$y,$$x)如果($$x gt$$y);
$i++;
}
}
打印“@list\n”;

交换行是可怕的,因为它显式地交换显式引用。

所以不是一个为我编写代码的站点。你必须自己尝试,当你被困在某个地方时,在这里陈述你的问题,然后你会得到帮助。以上是我尝试过的如果你在第二个版本中追求速度,我敢肯定你让它变慢了。比较这两个,
($list[$i],$list[$i+1])=排序($list[$i],$list[$i+1])
my$r=sub{\\\}->($list[$i],$list[$i+1])@$r=排序@$r。我赌的是简单的那种。
#!/usr/bin/env perl
use strict;
use warnings;

my @list = ('a', 'b', '3', '5', '7', '4', 'd', 'c', '6', '3', '2');

for (my $i = 0; $i < scalar(@list); $i++)
{
    if ($list[$i] =~ m/[[:alpha:]]/)
    {
        my($x,$y) = (\$list[$i], \$list[$i+1]);
        ($$x, $$y) = ($$y, $$x) if ($$x gt $$y);
        $i++;
    }
}

print "@list\n";