簡體   English   中英

Perl PDL:搜索向量是在數組中還是在矩陣中

[英]Perl PDL : Search if a vector is in an array or in a matrix

我嘗試在 PDL 矩陣或 Vector 數組上制作 grep:

my @toto;
push(@toto, pdl(1,2,3));
push(@toto, pdl(4,5,6));
my $titi=pdl(1,2,3);
print("OK") if (grep { $_ eq $titi} @toto);

我也試過

my @toto;
push(@toto, pdl(1,2,3));
push(@toto, pdl(4,5,6));
my $titi=pdl(1,2,3);
print("OK") if (grep { $_ eq $titi} PDL::Matrix->pdl(\@toto));

沒有工作。

任何幫助請

免責聲明:我對PDL一無所知。 我已經閱讀了這個消息來源。

有一個函數PDL::all()可以與重載的比較運算符==一起使用。

use PDL;
my $foo = pdl(1,2,3);
my $bar = pdl(4,5,6);
my $qrr = pdl(1,2,3);

print "OK 1" if PDL::all( $foo == $bar );
print "OK 2" if PDL::all( $foo == $qrr );

我還在尋找文檔。

以可縮放的方式有效地執行此操作的方法是使用PDL::VectorValued::Utils和兩個 ndarray(“haystack”是一個 ndarray,而不是 Perl ndarray 數組)。 小的 function vv_in沒有顯示為復制粘貼到perldl CLI 中,因為從這個答案中復制粘貼它的可能性較小:

sub vv_in {
  require PDL::VectorValued::Utils;
  my ($needle, $haystack) = @_;
  die "needle must have 1 dim less than haystack"
    if $needle->ndims != $haystack->ndims - 1;
  my $ign = $needle->dummy(1)->zeroes;
  PDL::_vv_intersect_int($needle->dummy(1), $haystack, $ign, my $nc=PDL->null);
  $nc;
}
pdl> p $titi = pdl(1,2,3)
[1 2 3]
pdl> p $toto = pdl([1,2,3], [4,5,6])
[
 [1 2 3]
 [4 5 6]
]
pdl> p $notin = pdl(7,8,9)
[7 8 9]
pdl> p vv_in($titi, $toto)
[1]
pdl> p vv_in($notin, $toto)
[0]

請注意,為了提高效率, $haystack需要已經排序(使用qsortvec )。 dummy對象“膨脹” $needle使其成為具有一個向量的向量集,然后vv_intersect返回兩個 ndarray:

  • 相交向量集(這里總是單個向量)或一組零(可能是例程的一個缺點,它應該是vectorlength,0 - 一個空的 ndarray)
  • 找到的向量數量(此處為 0 或 1)

使用“內部”( _vv_intersect_int ) 版本是因為從 PDL::VectorValued 1.0.15 開始,它有一些不允許廣播的包裝 Perl 代碼(已提交 問題)。

注意vv_in將在多組輸入向量和輸入干草堆上“廣播”(以前稱為“線程”,令人困惑)。 這可用於搜索多個向量:

sub vv_in_multi {
  my ($needles, $haystack) = @_;
  die "needles must have same number of dims as haystack"
    if $needles->ndims != $haystack->ndims;
  vv_in($needles, $haystack->dummy(-1));
}
pdl> p vv_in_multi(pdl($titi,$notin), $toto)
[1 0]

感謝 Ed 上面的 VectorValued 大喊(以及錯誤報告)。 回想起來,我發現如果$toto被排序(la qsortvec() ,就像在你的例子中一樣),你可以使用vsearchvec() ,也來自 PDL::VectorValued::Utils 並且通常更快比vv_intersect (對數與線性):

sub vv_in_vsearch {
  require PDL::VectorValued::Utils;
  my ($needle, $haystack) = @_;
  my $found = $needle->vsearchvec($haystack);
  return all($haystack->dice_axis(1,$found) == $needle);
}
pdl> $titi = pdl(1,2,3)
pdl> $tata = pdl(4,5,6)
pdl> $toto = pdl([1,2,3], [4,5,6])
pdl> $notin = pdl(7,8,9)
pdl> p vv_in_vsearch($titi, $toto)
1
pdl> p vv_in_vsearch($tata, $toto)
1
pdl> p vv_in_vsearch($notin, $toto)
0

(完全披露:我編寫並維護 PDL::VectorValued)

您可以使用Test::PDL eq_pdl

use PDL;
use Test::PDL qw( eq_pdl );
my @toto;
push(@toto, pdl(1,2,3));
push(@toto, pdl(4,5,6));
my $titi = pdl(4,5,6);
print("OK\n") if (grep { eq_pdl( $_, $titi) } @toto);

輸出

OK

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM