如何从矩阵中删除多个列

时间:2018-01-21 04:06:54

标签: matrix fortran

Integer :: NBE,ierr,RN,i,j
Real(kind=8), allocatable :: AA1(:,:),AA2(:,:)

NBE=40 
RN=3*NBE-2
Allocate(AA1(3*NBE,3*NBE),AA2(3*NBE,RN),stat=ierr)

If (ierr .ne. 0) Then
    print *, 'allocate steps failed 1'
    pause
End If

Do i=1,3*NBE
  Do j=1,3*NBE
     AA1(i,j)=1
  End Do
End Do

我想从矩阵AA1中删除列97和113,然后此矩阵变为AA2。我只想知道Fortran的任何命令是否可以实现此操作?

3 个答案:

答案 0 :(得分:5)

这是一个简单的一个班轮:

AA2 = AA1(:,[(i,i=1,96),(i=98,112),(i=114,3*NBE)])

说明:

  1. (内部部分)为索引[1,...,96,98,...,112,114,...,3*NBE]构建临时数组

  2. (外部)复制矩阵并仅考虑索引数组中的列

  3. 好的,我屈服于@IanBush ......更简单的是做三个专门的任务:

    AA2(:,1:96)   = AA1(:,1:96)
    AA2(:,97:111) = AA1(:,98:112)
    AA2(:,112:)   = AA1(:,114:)
    

答案 1 :(得分:5)

Alexander Vogt's answer给出了使用向量下标来选择要包含的数组元素的概念。该答案使用

构造了矢量下标数组
[(i,i=1,96),(i=98,112),(i=114,3*NBE)]

有些人可能会考虑

AA2 = AA1(:,[(i,i=1,96),(i=98,112),(i=114,3*NBE)])

在阅读中不太清楚。人们可以使用"临时"索引向量

integer selected_columns(RN)
selected_columns = [(i,i=1,96),(i=98,112),(i=114,3*NBE)]
AA2 = AA1(:,selected_columns)

但是这并没有解决数组构造函数不好的问题,特别是在更复杂的情况下。相反,我们可以创建一个掩码并使用我们常用的技术:

logical column_wanted(3*NBE)
integer, allocatable :: selected_columns(:)

! Create a mask of whether a column is wanted
column_wanted = .TRUE.
column_wanted([97,113]) = .FALSE.

! Create a list of indexes of wanted columns
selected_columns = PACK([(i,i=1,3*NBE)],column_wanted)
AA2 = AA1(:,selected_columns)

答案 2 :(得分:1)

我家里没有Fortran编译器,所以我不能测试它。但是,我做了一些事情:

i = 0
DO j = 1, 3*NBE
    IF (j == 97 .OR. j == 113) CYCLE
    i = i + 1
    AA2(:, i) = AA1(:, j)
END DO

CYCLE命令意味着不应该再执行循环的其余部分,并且应该开始下一次迭代。因此,i不会增加,所以当j=96i=96j=98然后i=97,以及j=114i=112 1}}。

更多的话:由于Fortran的内存布局,您希望以最快的速度循环第一个索引,依此类推。因此,如果将代码更改为:

,则代码运行速度会更快
Do j=1,3*NBE    ! Outer loop over second index
  Do i=1,3*NBE  ! Inner loop over first index
    AA1(i,j)=1
  End Do
End Do

(当然,仅使用AA1(:,:) = 1的{​​{1}}就可以轻松完成这种简单的初始化。