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

jft*_*sai 14 sorting perl

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

my @A = ([2,3,1], [1,2,3], [1,0,2], [3,1,2], [2,2,4]);
Run Code Online (Sandbox Code Playgroud)

我想按升序排序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";
}
Run Code Online (Sandbox Code Playgroud)

结果:

1,2,3
1,0,2
2,3,1
2,2,4
3,1,2
Run Code Online (Sandbox Code Playgroud)

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

1,0,2
1,2,3
2,2,4
2,3,1
3,1,2
Run Code Online (Sandbox Code Playgroud)

我的比较函数有错误吗?奇怪的是,当我将比较代码放入块中时,结果被正确排序.

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

tad*_*dmc 22

你正在执行

return ($a->[0] <=> $b->[0])
Run Code Online (Sandbox Code Playgroud)

它在到达任何"或"子句之前返回.

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

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

  • *OR*使用更严格的绑定或:`||`. (9认同)

pwe*_*wes 9

您观察到这种"错误"行为的原因是or操作员的优先级,尽可能低.在这种情况下,这意味着

return ($a->[0] <=> $b->[0]) or 
       ($a->[1] <=> $b->[1]) or
       ($a->[2] <=> $b->[2]);
Run Code Online (Sandbox Code Playgroud)

被解释为OR-ing

return ($a->[0] <=> $b->[0])
Run Code Online (Sandbox Code Playgroud)

和其余的一行 - 在这种情况下是废话,因为回报永远不会回来.:)

所以你应该使用C的OR:

return ($a->[0] <=> $b->[0]) || 
       ($a->[1] <=> $b->[1]) ||
       ($a->[2] <=> $b->[2]);
Run Code Online (Sandbox Code Playgroud)


Dan*_*her 5

需要更多括号:

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


小智 5

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

您可以在此处删除“返回”。

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