我有一些长度相同的数组。我想对第一个数组进行排序,并使所有其他数组相应地“排序”。例如,如果第一个数组为(7,2,9)
,则第二个数组为("seven","two","nine")
,第三个数组为排序后的("VII","II","IX")
(根据第一个数组值递增),我们将(2,7,9)
("two","seven","nine")
和("II","VII","IX")
。
我该怎么做?
答案 0 :(得分:17)
虽然我同意eugene y和MvanGeest通常最好的答案是切换到另一个数据结构,但有时你可能想要并行数组(或者至少可能无法避免它们)实际上 是一种并行排序并行数组的方法。它是这样的:
my @nums = (7, 2, 9);
my @names = qw(seven two nine);
my @roman = qw(VII II IX);
my @sorted_indices = sort { $nums[$a] <=> $nums[$b] } 0..$#nums;
@$_ = @{$_}[@sorted_indices] for \(@nums, @names, @roman);
即,生成与所有数组对应的 indices 列表,然后根据将“主”数组按顺序排列的顺序对它们进行排序。一旦我们得到了索引的排序列表,就要重新排序所有数组以匹配。
最后一行可以写成
@nums = @nums[@sorted_indices];
@names = @names[@sorted_indices];
@roman = @roman[@sorted_indices];
但是我试图减少必要的复制粘贴量,即使是以一些略带毛茸茸的语法为代价。你知道的更多......
答案 1 :(得分:6)
我知道你已经接受了答案,还有其他非常好的答案 答案在这里,但我会提出一些不同的东西:不要复制你的 数据。你只需要跟踪阿拉伯语 - &gt;罗马映射一次 - 为什么 存储什么是基本上重复的数字数组,并对每个数字进行排序? 只需对主列表进行排序,并根据需要在参考数组中查找其他值:
my @roman = qw(0 I II III IV V VI VII VIII IX X);
my @text = qw(zero one two three four five six seven eight nine ten);
my @values = (7, 2, 9);
my @sorted_values = sort @values;
my @sorted_roman = map { $roman[$_] } @sorted_values;
my @sorted_text = map { $text[$_] } @sorted_values;
use Data::Dumper;
print Dumper(\@sorted_values, \@sorted_roman, \@sorted_text);
打印:
$VAR1 = [
2,
7,
9
];
$VAR2 = [
'II',
'VII',
'IX'
];
$VAR3 = [
'two',
'seven',
'nine'
];
在真实环境中,我建议使用库来执行 罗马和文字转换:
use Roman;
my @sorted_roman = map { roman($_) } @sorted_values;
use Lingua::EN::Numbers 'num2en';
my @sorted_text = map { num2en($_) } @sorted_values;
答案 2 :(得分:5)
将数据重新组织到单个数组中进行排序:
my @a = ([7, "seven", "VII"], [2, "two", "II"], ..);
@a = sort { $a->[0] <=> $b->[0] } @a;
然后重新创建原始数组:
my(@a1, @a2, @a3);
for (@a) {
push @a1, shift @$_;
push @a2, shift @$_;
push @a3, shift @$_;
}
答案 3 :(得分:4)
正如您所发现的,维护并行阵列可能很麻烦且容易出错。另一种方法是将相关信息保存在一起。
use strict;
use warnings;
# One array-of-hashes instead of three parallel arrays.
my @numbers = (
{ arabic => 7, text => 'seven', roman => 'VII' },
{ arabic => 2, text => 'two', roman => 'II' },
{ arabic => 9, text => 'nine', roman => 'IX' },
);
@numbers = sort { $a->{arabic} <=> $b->{arabic} } @numbers;