是否存在与Matlab ismember函数等效的Fortran实现?及代码优化问询
求等效于Matlab
ismember函数的Fortran实现及循环简化问题 原Matlab需求
我需要实现Matlab中ismember(A,B(i,:),'rows')的等效Fortran功能,核心作用是检查矩阵B的每一行是否在矩阵A中存在完全匹配的行。
Matlab示例代码
A = [1 0 0 1;0 1 1 0;0 1 1 0;]; B = [0 1 1 0;1 0 0 1;0 0 0 0;]; l = size(A,1); for i = 1:l I = ismember(A,B(i,:),'rows'); indx = find (I == 1) end
输出结果
indx = 2 3 indx = 1 indx = 0×1 empty double column vector
我的Fortran代码问题
我编写了以下Fortran程序:其中两层循环的第一部分能得到正确结果,但尝试简化为一层循环的第二部分无法输出预期结果。请问如何修改第二部分代码实现需求?
program ismember implicit none integer :: i,j, i_ind, ii integer, parameter :: N_lines = 5, N_columns = 3 integer, allocatable :: AA1(:,:),AA4(:,:) integer, allocatable :: indices(:) logical :: row_wanted2(N_lines) ! --------------------------- 定义矩阵AA1 ---------------------------! Allocate(AA1(N_lines,N_columns)) do i=1,N_lines do j=1,N_columns AA1(i,j)= i + j end do end do print*, 'AA1' do i = 1, N_lines write(*,"(1X,10I5)") (AA1(i,j), j = 1, N_columns) end do ! --------------------------- 定义矩阵AA4 ---------------------------! Allocate(AA4(N_lines,N_columns)) AA4(1,:) = AA1(5,:) AA4(3,:) = AA1(1,:) AA4(5,:) = AA1(3,:) AA4(2,:) = 0 AA4(4,:) = 0 print*, 'AA4' do i = 1, N_lines write(*,"(1X,10I5)") (AA4(i,j), j = 1, N_columns) end do ! --------------------------- ismember逻辑 ---------------------------! print*, 'AA1 行数', size(AA1,1) print*, 'AA1 列数', size(AA1,2) row_wanted2 = .true. ! --------------------------- 第一部分:两层循环(正确) ---------------------------! do i = 1, size(AA1,1) print*, i do ii = 1, size(AA4,1) if ( all( AA1(i,:) == AA4(ii,:) ) ) then print *, "AA1与AA4当前行匹配" else print *, "AA1与AA4当前行不匹配" end if end do end do ! --------------------------- 第二部分:简化循环(错误) ---------------------------! do i = 1, size(AA1,1) indices = pack([(i_ind,i_ind=1,size(AA1,1))], all(AA1(i,:) == AA4(i_ind,:)) ) if(size(indices).ge.1) then print*, 'indices', indices print*, '找到匹配' else row_wanted2(i) = .false. print*, '未找到匹配' endif deallocate(indices) end do end program ismember
问题分析与修正
你的第二部分代码存在两个核心问题:
- 循环对象逻辑错误:Matlab代码是遍历B的每一行查找A中的匹配行,但你的Fortran代码遍历的是AA1的行,与原需求逻辑相反;
- 数组构造器中
all的使用方式错误:直接在pack的条件中使用all(AA1(i,:) == AA4(i_ind,:))无法正确遍历所有行完成整行匹配判断。
完全匹配Matlab逻辑的修正代码
以下代码实现与Matlab示例完全一致的功能:遍历AA4(对应Matlab的B)的每一行,查找AA1(对应Matlab的A)中匹配的行索引。
! --------------------------- 修改后的第二部分(匹配Matlab逻辑) ---------------------------! do i = 1, size(AA4,1) ! 遍历AA4的每一行,对应Matlab中的B(i,:) ! 构造逻辑数组:标记AA1中每一行是否与AA4(i,:)完全匹配 logical, allocatable :: match(:) allocate(match(size(AA1,1))) match = [(all(AA1(ii,:) == AA4(i,:)), ii=1, size(AA1,1))] ! 提取AA1中匹配行的索引 indices = pack([(ii, ii=1, size(AA1,1))], match) if(size(indices) >= 1) then print*, 'AA4行', i, '在AA1中的匹配行索引:', indices print*, '找到匹配' else print*, 'AA4行', i, '未在AA1中找到匹配' print*, '空索引数组' endif deallocate(indices, match) end do
若需求为遍历AA1找AA4中的匹配
如果你的实际需求是遍历AA1的行,查找AA4中的匹配行,可使用以下修正代码:
! --------------------------- 修改后的第二部分(遍历AA1找AA4匹配) ---------------------------! do i = 1, size(AA1,1) logical, allocatable :: match(:) allocate(match(size(AA4,1))) match = [(all(AA1(i,:) == AA4(ii,:)), ii=1, size(AA4,1))] indices = pack([(ii, ii=1, size(AA4,1))], match) if(size(indices) >= 1) then print*, 'AA1行', i, '在AA4中的匹配行索引:', indices print*, '找到匹配' else row_wanted2(i) = .false. print*, 'AA1行', i, '未在AA4中找到匹配' endif deallocate(indices, match) end do
关键修正说明
- 逻辑数组构造:通过数组构造器
[(all(行1 == 行2), 索引遍历)]生成逐行匹配的逻辑标记,确保整行比较的正确性; - 索引提取正确:
pack函数根据逻辑数组提取对应矩阵的行索引,完全对齐Matlab中find(ismember(...))的输出; - 循环对象对齐需求:根据实际需求选择遍历AA4或AA1的行,保证逻辑与原需求一致。
内容的提问来源于stack exchange,提问作者user790082
相关产品推荐
相关产品推荐

