Perl PDL技术问询:如何判断向量是否存在于数组或矩阵中
在PDL数组中实现类似grep的匹配功能
我来帮你搞定这个问题~你遇到的核心问题是PDL对象的比较方式和普通Perl标量/数组不一样,直接用eq或者默认的比较逻辑没法正确判断两个PDL是否完全匹配。
为什么你的代码不工作?
PDL重载了eq和==操作符:
eq针对PDL对象时,是做逐元素的字符串比较,返回的是一个PDL布尔矩阵,不是Perl能识别的真假值- 即使你用
==(逐元素数值比较),返回的依然是PDL对象,而Perl的grep会把任何非空的PDL对象都视为“真”,所以没法正确筛选出完全匹配的元素
正确的解决方案
1. 基础版:匹配所有元素相同的PDL
用PDL的all方法,把逐元素比较的结果转换成Perl的布尔值(当所有元素都相等时返回1,否则返回0):
use PDL; my @toto; push(@toto, pdl(1,2,3)); push(@toto, pdl(4,5,6)); my $titi = pdl(1,2,3); print("OK") if grep { ($_ == $titi)->all } @toto;
这段代码会正确输出OK,因为($_ == $titi)生成一个全1的PDL布尔数组,->all把它转换成Perl的真,grep就能找到匹配的元素。
2. 进阶版:严格匹配维度+元素
如果你的数组里可能存在不同维度的PDL(比如一维向量和二维矩阵),可以先检查维度是否一致,再比较元素:
use PDL; my @toto; push(@toto, pdl(1,2,3)); push(@toto, pdl([4,5,6])); # 二维矩阵 my $titi = pdl(1,2,3); print("OK") if grep { $_->dims eq $titi->dims && ($_ == $titi)->all } @toto;
$_->dims会返回PDL的维度信息(比如一维是(3),二维是(1,3)),用eq比较维度的字符串化结果,确保两个PDL的结构完全一致,再结合元素全相等的判断,避免误匹配。
关于PDL::Matrix的尝试
你用PDL::Matrix->pdl(\@toto)会把数组转换成一个二维PDL矩阵,这时候grep遍历的是矩阵的扁平化元素列表,而不是原来的每个PDL对象,这显然不是你想要的逻辑。所以保持@toto为PDL对象的数组是更直接的做法。
内容的提问来源于stack exchange,提问作者Alexglvr
相关产品推荐
相关产品推荐

