我有一个一维PDL,我想对每一半执行一次计算;即将其分开,然后在上半场进行计算,在下半场进行相同的计算。将PDL分成两部分
是否有一个更容易/更好/优雅的方式来简单地将PDL分成两半来获取元素数量(使用nelem),将其分成两部分,然后分两部分?
感谢
我有一个一维PDL,我想对每一半执行一次计算;即将其分开,然后在上半场进行计算,在下半场进行相同的计算。将PDL分成两部分
是否有一个更容易/更好/优雅的方式来简单地将PDL分成两半来获取元素数量(使用nelem),将其分成两部分,然后分两部分?
感谢
是的,只要你不需要直接调用切片得到你想要的。你可以链splitdim
和dog
像这样的东西:
# Assume we have $data, a piddle
my ($left, $right) = $data->splitdim(0, $data->nelem/2)->dog;
那当然了,很容易扩展到两个以上的部门。但是,如果您想将其扩展到更高维度的小提琴(即时间序列的所有集合存储在一个小提琴中),您需要稍微微妙一些。如果你想沿着第一维度(具有索引0)分开,你反而会这样说:
# Assume we have $data, a piddle
my ($left, $right) = $data->splitdim(0, $data->dim(0)/2)->mv(1, -1)->dog;
的splitdim
操作拆分零维到二维,第0是暗淡(0)/ 2长度,第一个长度为2(因为我们将它分成两部分)。由于dog
在最后一维上运行,因此我们在调用dog
之前将第1维移至末尾。
但是,即使使用单维解决方案,也存在一个警告。由于$data->splitdim
的工作方式,如果您有奇数个元素,它将截断最后一条数据。尝试在一个小罐该操作有21个元素,你会明白我的意思:
my $data = sequence(20);
say "data is $data"; # lists 0-19
my ($left, $right) = $data->splitdim(0, $data->nelem/2)->dog;
say "left is $left and right is $right"; # lists 0-9, then 10-19
$data = sequence(21);
say "data is $data"; # lists 0-20, i.e. 21 elements
my ($left, $right) = $data->splitdim(0, $data->nelem/2)->dog;
say "left is $left and right is $right"; # lists 0-9, then 10-19!!
如果你想避免这种情况,你可以制作自己的方法,其将第一维一半没有截断。或许,这将是这个样子:
sub PDL::split_in_half {
my $self = shift;
# the int() isn't strictly necessary, but should make things a
# tad faster
my $left = $self->slice(':' . int($self->dim(0)/2-1));
my $right = $self->slice(int($self->dim(0)/2) . ':');
return ($left, $right);
}
在这里,我也有使用int
内置,以确保我们没有.5
如果dim(0)
是奇数。这是一个有点复杂,但我们埋葬了这种复杂性为方法精确,所以我们不必去想的复杂性,所以我们不妨买自己几个时钟周期,而我们在这。
然后,你可以很容易地这样调用方法:
my ($left, $right) = $data->split_in_half;