我有以下数组模式: 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++
}
然后尝试用splice替换这些部分。
此外,我尝试了以下似乎有效:
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,$_;
}
}
我想知道是否有更高效和Perlish风格的方式来做到这一点?
答案 0 :(得分:1)
一种方法是循环数组一次,保持序列中遇到的第一个数字的索引。遇到字符(意味着数字序列已结束),然后直接在该数组切片中对数字序列进行排序
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";
答案 1 :(得分:0)
这更令人满意吗?
#!/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";
概念是当当前条目是字母时,下一个条目也必须是,所以对该数组的片进行排序并增加$i
,以便不单独处理第二个字母字符。示例输出为:
a b 3 5 7 4 c d 6 3 2
我对排序中的重复切片并不完全满意,但我不确定在使用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
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";
交换行很可怕,因为它明确地交换显式引用。