Arrays perl数组中的对重排序

Arrays perl数组中的对重排序,arrays,perl,Arrays,Perl,我从另一个程序向perl程序提供了一系列二维坐标。其中有4个组成四元组,总共有8个数字,例如: x1 y1 x2 y2 x3 y3 x4 y4 我想确保它们都按相同的顺序指定,即顺时针或逆时针。我已经知道如何做到这一点,并且正在通过观察交叉积的迹象来做到这一点 use strict; use warnings; my $line = "-0.702083 0.31 -0.676042 -0.323333 0.74375 -0.21 0.695833 0.485"; my @coord = sp

我从另一个程序向perl程序提供了一系列二维坐标。其中有4个组成四元组,总共有8个数字,例如:

x1 y1 x2 y2 x3 y3 x4 y4

我想确保它们都按相同的顺序指定,即顺时针或逆时针。我已经知道如何做到这一点,并且正在通过观察交叉积的迹象来做到这一点

use strict;
use warnings;

my $line = "-0.702083 0.31 -0.676042 -0.323333 0.74375 -0.21 0.695833 0.485";
my @coord = split(/[,\s]+/, $line);

# Vector cross product (Z is 0) to test CW/CCW
my @v1 = (-$coord[2]+$coord[0], -$coord[3]+$coord[1]);
my @v2 = (-$coord[2]+$coord[4], -$coord[3]+$coord[5]);
my $cross = ($v1[0]*$v2[1]) - ($v1[1]*$v2[0]);
确定订单是否需要更改后,我现在使用以下方法进行更改:

@coord = ($coord[6], $coord[7], $coord[4], $coord[5], 
          $coord[2], $coord[3], $coord[0], $coord[1]) if ($cross < 0);
@coord=($coord[6]、$coord[7]、$coord[4]、$coord[5],
$coord[2]、$coord[3]、$coord[0]、$coord[1])如果($cross<0);

这是可行的,但我相当肯定这不是用perl编写它的最好方式。是否有一种更优雅的“perly”方式来按顺序书写这种变化?适合
$n
2-D对的东西。这不是简单的数组元素反转问题。

最后几行可以使用数组切片重写:

@coord = @coord[6,7,4,5,2,3,0,1] if $cross < 0;

对于
$n
2-D对,您需要一个函数来返回新排序的列表。
例如,
$n==8

sub reorder {
    my $n = shift;
    return (6,7,4,5,2,3,0,1) if $n == 8;
}
然后您可以在数组切片中使用它:

$n = 8;
@coord = @coord[reorder($n)] if $cross < 0;
$n=8;
@如果$cross<0,则coord=@coord[重新排序($n)];

基于尤金的答案。建立反向列表的方法:

my $i = 0; 
unshift @i, $i++, $i++ while ($i <= $#coord); 
@coord = @coord[@i];
my$i=0;

unshift@i,$i++,$i++,$i++,$i++,$i我最近遇到了一个类似的问题,并解决了这个简洁的算法:

splice @coords, $_, 2, [ $coords[$_],$coords[$_+1] ]  for 0..$#coords/2;
@coords = map { @$_ } reverse @coords;
第一行将平面列表转换为坐标对列表,例如,
(0,1,10,11,50,51)=>([0,1],[10,11],[50,51])

第二行反转成对的顺序并再次展平列表


更新:更加简洁:

@coords = @coords[reverse map{$_ ^ 1}0..$#coords] if $cross < 0;

@coords = @coords[map {-$_ ^ 1} 1..@coords] if $cross < 0;

@coords = @coords[map {$_ ^ -1} 1..@coords] if $cross < 0;
@coords=@coords[如果$cross<0,则反向映射{$^1}0..$#coords];
@coords=@coords[map{-$^1}1..@coords]如果$cross<0;
@如果$cross<0,则coords=@coords[map{$\u^-1}1..@coords];

+1,感谢您缺少语法。切片的标记可以是列表,或者更好的是生成该序列的表达式吗?@awoodland:当然。例如,您可以说
@arr[0..3]
。即使在双引号from中插入一个片段,这也能起作用:在同一条语句中两次修改变量将导致未定义的行为perlop说这是一件荒谬的事情;一般来说,在更复杂的情况下,理解执行顺序需要一些工作,在某些情况下,这会变得更加困难,但是t它是定义良好的(至少由perl源代码:)并且不会更改。我认为添加该评论只是为了回应那些试图混淆自己的人。@ysth,虽然大多数情况下是正确的,但也有一些情况依赖于所使用的C编译器。而C标准也规定了同样的情况是未定义的行为。嗯,不,这是完全错误的,文塔苏
@coords = @coords[reverse map{$_ ^ 1}0..$#coords] if $cross < 0;

@coords = @coords[map {-$_ ^ 1} 1..@coords] if $cross < 0;

@coords = @coords[map {$_ ^ -1} 1..@coords] if $cross < 0;