我有一個一維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;