2011-01-05 60 views
5

我是Perl新手,並且遇到了一個(可能很簡單)的數組排序問題。在Perl中進行數組排序

我已經繼承了一些Perl代碼,它將文本文件中的行讀入三個一維數組(x,y,z)。我希望能夠使用其中一個維度作爲關鍵字對這些數組進行排序,並將其他兩個維度重新排序以匹配。

例如,如果我的輸入是:

  • @x =(1,3,2)
  • @y =(11,13,12)
  • @z =(21, 23,22)

和我排序的x,我想得到的結果是:

  • @x =(1,2,3)
  • @y =(11,12,13)
  • @z =(21,22,23)

我可以在三個1 d陣列合併成2-d陣列如果使壽命更輕鬆。

+0

您的示例數據可能被清除 - 在@y的價值觀和@z與@x的順序相同。具有非常不同的值(或者甚至類似'a','b','c'的東西)將使它更清楚地知道它們如何被排序 – plusplus 2011-01-05 17:57:11

回答

3
use strict; 
use warnings; 
use Data::Dumper; 

use List::Util qw(reduce); 

my @x = (1, 3, 2); 
my @y = (11, 13, 12); 
my @z = (21, 23, 22); 

my @combined = map { [ $x[$_], $y[$_], $z[$_] ] } 0 .. $#x; 
my @sorted = sort { $a->[0] <=> $b->[0] } @combined; 
my $split_ref = reduce { push @{$a->[$_]}, $b->[$_] for 0 .. $#$a; $a;} [[], [], []], @sorted; 

print Dumper \@combined; 
print Dumper \@sorted; 
print Dumper $split_ref; 

這將基本上給你:

[ 
     [ 
     1, 
     2, 
     3 
     ], 
     [ 
     11, 
     12, 
     13 
     ], 
     [ 
     21, 
     22, 
     23 
     ] 
    ]; 
+0

這工作很好...謝謝! – amb 2011-01-05 15:55:52

-1

@a = sort { $a <=> $b } @a; 

另見sort on perldoc

+1

這不會對'@ y'或'@ z'進行排序。 – mkb 2011-01-05 15:17:12

+0

是的,這將排序一維數組中的一個。它不會對其他兩個進行排序。我希望能夠通過x數組進行排序,並將y和z數組重新排序以匹配,以便保留文本文件中的行。如果我的問題不清楚,我很抱歉。 --amb – amb 2011-01-05 15:17:30

0

合併確實可能會使生活更輕鬆。

@sorted = sort { $a->[0] <=> $b->[0] } 
    ([$x[0], $y[0], $z[0]], [$x[1], $y[1], $z[1]], [$x[2], $y[2], $z[2]]); 

可能會這樣做。你當然不想用手寫出所有的東西!

0

如果@x與@y和@z的大小相同,則不需要排序 - 您可以改爲使用數組切片!

use strict; 
use warnings; 
use 5.010; 

my @x = (1, 3, 2); 
my @y = (11,13,12); 
my @z = (21,23,22); 

say join ', ', @y; 
@y = @y[ map { $_ - 1 } @x ]; #We use map create a lists of the values of elements in @x, minus 1. 
say join ', ', @y; 

當然,如果你只是想通過數字順序進行排序,然後使用@x是多餘的:

@y = sort { $a <=> $b } @y; 

最後,如果要排序數組的任意號碼,你可以創建數組的數組,或通過引用列表到了,阿拉

my @indexes = map { $_ - 1 } @x; 

for my $array_ref (\@x, \@y, \@z) { 
    @$array_ref = @{$array_ref}[@indexes]; 
} 
+1

我不認爲你可以放心地假設'@ x'中的值可以用作索引。如果它們是否定的或不唯一的呢? – mkb 2011-01-05 15:23:29

+0

負數或重複不會真的很麻煩(畢竟這是他的規範..),但數組之外的索引將觸發警告。但是,請注意程序員。 – Hugmeir 2011-01-05 15:32:42

+0

他們很麻煩,因爲他們會在沒有警告的情況下給你不正確的結果。嘗試改變未排序的@ x'到(1,3,3)。 – mkb 2011-01-05 15:49:16

0

有一試:

#!/usr/bin/perl 
use 5.10.1; 
use strict; 
use warnings; 
use Data::Dumper; 

my @x = (1, 3, 2); 
my @y = (11,13,12); 
my @z = (21,23,22); 

my (%y, %z); 

@y{@x} = @y; 
@z{@x} = @z; 

my @xs = sort @x; 
my @ys = @y{@xs}; 
my @zs = @z{@xs}; 
say Dumper \@xs,\@ys,\@zs; 

輸出:

$VAR1 = [ 
      1, 
      2, 
      3 
     ]; 
$VAR2 = [ 
      11, 
      12, 
      13 
     ]; 
$VAR3 = [ 
      21, 
      22, 
      23 
     ]; 
+1

如果@ x具有任何重複值,則會中斷。 – mkb 2011-01-05 15:50:25

10

合併所有的數組在一起是沒有必要的。使用sort以獲取元素的正確索引排序在@x

@sort_by_x = sort { $x[$a] <=> $x[$b] } 0 .. $#x; # ==> (0, 2, 1) 

那麼該索引的順序適用於任何其他數組:

@x = @x[@sort_by_x]; 
@y = @y[@sort_by_x]; 
@z = @z[@sort_by_x];