2011-01-05 61 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];