我想在Perl中对数组进行排序,但结果没有排序

时间:2012-01-13 12:50:16

标签: perl sorting

我有一个我要排序的数组。数组A的每个元素是一个包含3个元素的数组。 数组A看起来像:

my @A = ([2,3,1], [1,2,3], [1,0,2], [3,1,2], [2,2,4]);

我想按升序排序A.比较2个元素时,使用第一个数字。如果存在平局,则使用第二个数字,然后使用第三个数字。

这是我的代码。我使用函数'cmpfunc'来比较2个元素。

sub cmpfunc {
    return ($a->[0] <=> $b->[0]) or 
           ($a->[1] <=> $b->[1]) or
           ($a->[2] <=> $b->[2]);
}
my @B = sort cmpfunc @A;
print "Result:\n";
for my $element (@B) {
    print join(",", @{$element}) . "\n";
}

结果:

1,2,3
1,0,2
2,3,1
2,2,4
3,1,2

结果有些分类,但不正确。我的期望是:

1,0,2
1,2,3
2,2,4
2,3,1
3,1,2

我的比较功能有错误吗? 奇怪的是,当我把比较代码放在块中时,结果被正确排序。

my @C = sort { ($a->[0] <=> $b->[0]) or 
               ($a->[1] <=> $b->[1]) or
               ($a->[2] <=> $b->[2]) } @A;

5 个答案:

答案 0 :(得分:21)

您正在执行

return ($a->[0] <=> $b->[0])

在到达任何“或”子句之前返回。

删除“return”关键字,或在整个 arg列表周围添加括号以便返回:

sub cmpfunc {
    return(($a->[0] <=> $b->[0]) or
           ($a->[1] <=> $b->[1]) or
           ($a->[2] <=> $b->[2]));
}

答案 1 :(得分:9)

您观察到这种“错误”行为的原因是or运算符的优先级,尽可能低。在这种情况下,这意味着

return ($a->[0] <=> $b->[0]) or 
       ($a->[1] <=> $b->[1]) or
       ($a->[2] <=> $b->[2]);

被解释为OR-ing

return ($a->[0] <=> $b->[0])

和其余部分 - 在这种情况下是废话,因为return永远不会返回。 :)

所以你应该使用C的OR:

return ($a->[0] <=> $b->[0]) || 
       ($a->[1] <=> $b->[1]) ||
       ($a->[2] <=> $b->[2]);

答案 2 :(得分:5)

需要更多括号:

sub cmpfunc {
    return (($a->[0] <=> $b->[0]) or
            ($a->[1] <=> $b->[1]) or
            ($a->[2] <=> $b->[2]));
}

答案 3 :(得分:3)

    sub cmpfunc {
    return ($a->[0] <=> $b->[0]) or 
           ($a->[1] <=> $b->[1]) or
           ($a->[2] <=> $b->[2]);
}

你可以在这里删除'return'。

    sub cmpfunc {
     ($a->[0] <=> $b->[0]) or 
     ($a->[1] <=> $b->[1]) or
     ($a->[2] <=> $b->[2]);
}

答案 4 :(得分:2)

丹尼尔的另一种解决方案:

sub cmpfunc {
    return ($a->[0] <=> $b->[0]) ||
           ($a->[1] <=> $b->[1]) ||
           ($a->[2] <=> $b->[2]);
}

or这种情况的问题是它的优先级低于赋值,所以你的函数只返回($a->[0] <=> $b->[0])的结果,如果左边是,则返回-1,0或1数值上分别低于,等于或大于右侧。 ||具有更高的优先级,因此在返回之前会评估整个布尔表达式。如上所述,如果您希望将表达式括在||中,则可以将表达式括在括号中。我个人没有。