2013-11-21 54 views
2

我有一個一維PDL,我想對每一半執行一次計算;即將其分開,然後在上半場進行計算,在下半場進行相同的計算。將PDL分成兩部分

是否有一個更容易/更好/優雅的方式來簡單地將PDL分成兩半來獲取元素數量(使用nelem),將其分成兩部分,然後分兩部分?

感謝

回答

3

是的,只要你不需要直接調用切片得到你想要的。你可以鏈splitdimdog像這樣的東西:

# 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;