我在Fortran中有一个p p n数组,我想从那个更大的数组中提取k * k子数组。我试过这样,但不确定它是否有效:
do i=1,p
vp(i)=i
end do
help=y(1:p,t)*vp
do t = 1, n
A(1:k,1:k,t) = B(pack(help,help>0), pack(help,help>0), t)
end do
其中y包含值0和1,1意味着行/列想要子数组。这是否有效,如果没有,那么同样的事情是如何实现的?感谢。
答案 0 :(得分:0)
如果我理解你想要做什么,这里有一个示例程序,它提取选定的列和行,但不使用多数数组表示法。
program test
integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim) :: good_row = [.true., .false., .true.]
logical, dimension (Bdim) :: good_col = [.false., .true., .true.]
integer :: i, j, ia, ja, ib, jb
if (count (good_row) /= Adim .or. count (good_col) /= Adim) then
write (*, *) 'selection arrays not setup correctly.'
stop
end if
do i=1, Bdim
do j=1, Bdim
B (i,j) = i + i*j**2 ! test values
end do
end do
do i=1, Bdim
write (*, *) (B (i, j), j=1, Bdim)
end do
ia = 0
do ib=1, Bdim
if (good_row (ib)) then
ia = ia + 1
ja = 0
do jb=1, Bdim
if (good_col (jb)) then
ja = ja + 1
!write (*, *) ia, ja, ib, jb
A(ia,ja) = B(ib,jb)
end if
end do
end if
end do
write (*, *)
do i=1, Adim
write (*, *) (A (i, j), j=1, Adim)
end do
stop
end program test
答案 1 :(得分:0)
解决方案二,使用向量(1D数组)级别的数组操作 - 将主循环替换为:
ia = 0
do ib=1, Bdim
if (good_row (ib)) then
ia = ia + 1
A (ia,:) = pack (B(ib,:), good_col)
end if
end do
解决方案三,完全使用数组操作:
program test
integer, parameter :: Adim = 2
integer, parameter :: Bdim = 3
integer, dimension (Adim,Adim) :: A
integer, dimension (Bdim,Bdim) :: B
logical, dimension (Bdim,Bdim) :: mask
integer :: i, j
mask (1,:) = [.false., .true., .true.]
mask (2,:) = .false.
mask (3,:) = [.false., .true., .true.]
do i=1, Bdim
do j=1, Bdim
B (i,j) = i + i*j**2 ! test values
end do
end do
do i=1, Bdim
write (*, *) (B (i, j), j=1, Bdim)
end do
A = reshape ( pack (B, mask), [Adim, Adim] )
write (*, *)
do i=1, Adim
write (*, *) (A (i, j), j=1, Adim)
end do
stop
end program test
答案 2 :(得分:0)
不确定这些非代码片段是否对您有用;但
不要忘记您可以使用向量下标来获取数组部分,例如,您可以选择向量v的元素,如下所示:
v((/ 1,3,6,5,10 /))
矢量下标可以应用于排名大于1的数组。以这种方式弄清楚你的下标需求会让我头痛,但你可能想尝试一下。
答案 3 :(得分:0)
是的,它应该有效,你甚至不需要do t = ...
循环
program main
integer,dimension(3,3,2):: a
integer,dimension(4,4,2):: b
integer,dimension(4):: y
integer,dimension(4):: idx
integer:: i,j,k
y = (/ 1 , 0 , 1 , 1 /)
idx = (/ (i,i=1,4) /)
b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/))
a(:,:,:) = b( pack(idx,y>0) , pack(idx,y>0) , :)
print '(A2/,(4I4))','b=',b
print '(A2/,(3I4))','a=',a
end
使用gfortran 4.2.3编译正确地给了我
b=
111 112 113 114
121 122 123 124
131 132 133 134
141 142 143 144
211 212 213 214
221 222 223 224
231 232 233 234
241 242 243 244
a=
111 113 114
131 133 134
141 143 144
211 213 214
231 233 234
241 243 244
您也可以使用
k = count( y> 0)
a(1:k,1:k,:) = b( pack(idx,y>0) , pack(idx,y>0) , :)
或者想想使用LOGICAL .true。和.false。而不是1和0 ...
program main
integer,dimension(3,3,2):: a
integer,dimension(4,4,2):: b
logical,dimension(4):: y
integer,dimension(4):: idx
integer:: i,j,k
idx = (/ (i,i=1,4) /)
y = idx /= 2
b(:,:,:)=reshape((/((((i+10*j+100*k),i=1,4),j=1,4),k=1,2)/),(/4,4,2/))
k = count( y )
a(1:k,1:k,:) = b( pack(idx,y) , pack(idx,y) , :)
print '(A2/,(4I4))','b=',b
print '(A2/,(3I4))','a=',a
end