You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

是否存在与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 

问题分析与修正

你的第二部分代码存在两个核心问题:

  1. 循环对象逻辑错误:Matlab代码是遍历B的每一行查找A中的匹配行,但你的Fortran代码遍历的是AA1的行,与原需求逻辑相反;
  2. 数组构造器中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

关键修正说明

  1. 逻辑数组构造:通过数组构造器[(all(行1 == 行2), 索引遍历)]生成逐行匹配的逻辑标记,确保整行比较的正确性;
  2. 索引提取正确:pack函数根据逻辑数组提取对应矩阵的行索引,完全对齐Matlab中find(ismember(...))的输出;
  3. 循环对象对齐需求:根据实际需求选择遍历AA4或AA1的行,保证逻辑与原需求一致。

内容的提问来源于stack exchange,提问作者user790082

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 06:45:35