我有幾個相同長度的數組。我想排序第一個數組,並相應地使所有其他數組「排序」。例如,如果第一個數組是(7,2,9)
,第二個數組是("seven","two","nine")
,第三個數組是("VII","II","IX")
(按照第一個數組值遞增),我們將有(2,7,9)
("two","seven","nine")
和("II","VII","IX")
。如何在Perl中對並行數組進行排序?
我該怎麼做?
我有幾個相同長度的數組。我想排序第一個數組,並相應地使所有其他數組「排序」。例如,如果第一個數組是(7,2,9)
,第二個數組是("seven","two","nine")
,第三個數組是("VII","II","IX")
(按照第一個數組值遞增),我們將有(2,7,9)
("two","seven","nine")
和("II","VII","IX")
。如何在Perl中對並行數組進行排序?
我該怎麼做?
重新組織數據,以一個單一的陣列,用於排序:
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 @$_;
}
如你發現,保持平行陣列可以是一個麻煩和錯誤俯臥。另一種方法是將相關信息保存在一起。
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;
雖然我同意尤金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);
也就是說,產生指數對應於所有陣列的列表,然後根據,將放在「主」數組中的順序進行排序它們。一旦我們有了索引的排序列表,重新排列所有數組以匹配。
最後一行可以寫手寫出來作爲
@nums = @nums[@sorted_indices];
@names = @names[@sorted_indices];
@roman = @roman[@sorted_indices];
但我想,以減少所需的複製粘貼的量,甚至在某些微毛語法的成本。更多你知道...
+1光滑。根據以下幾行提出一個通用函數的概念:'sub sort_parallel_arrays {my($ comparator,@arrays)= @_; ''。 – FMc 2010-08-01 15:59:15
+1確實非常酷! – 2010-08-01 17:18:35
我知道你已經接受了一個答案,並且還有其他很好的 答案在這裏,但我會建議一些不同的:不要複製你的 數據。你只需要追蹤一次阿拉伯數字 - >羅馬映射 - 爲什麼 存儲基本上重複的數字數組,並對每一個數組進行排序? 只是排序主列表,並根據需要查找的引用數組中的其他值:
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;
+1:這與hobbs的建議非常相似,但語法更清晰,不是嗎? – 2010-08-02 06:27:09
@David:不是真的;霍布斯的方法仍然存儲每種格式的數字列表,對數字列表進行排序,然後使用這些列表的索引作爲指導來排序其他格式。我放棄了完全存儲其他值的列表,並且之後只需從主轉換表(或外部轉換模塊)查找它們。如果你要對需要同時排序的東西進行排序,但你不能輕易地從一個轉換到另一個(即你需要存儲兩個版本),hobbs的方法就是要走的路,否則,使用查找表。 – Ether 2010-08-02 15:23:28
我會使用一個複雜的數據結構,而不是數組(陣列,散列數組或哈希數組/哈希S)。 – MvanGeest 2010-08-01 13:52:00