使用向量访问N-D数组的元素 [英] Access element of N-D array using a vector

查看:59
本文介绍了使用向量访问N-D数组的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以访问数组 a 的第 n 个元素,其中n是一维数组和 size(n) a 的排名。

Is there a way I can access the nth element of an array a, where n is a 1D array and size(n) is the rank of a.

编辑2015-08-22 15:21

Edit 2015-08-22 15:21

我在想类似的东西

program Example1D
    integer :: a(6), b(1)

    a = reshape( (/ (i , i = 1, size(a) ) /) , shape(a) )
    b = (/ 5 /)

    write(*,*) a(b)

end program Example1D

所以我可以这样称呼

program Want2D
    integer :: a(6,5), b(2)

    a = reshape( (/ (i , i = 1, size(a) ) /) , shape(a) )
    b = (/ 5 , 3 /)

    write(*,*) a(b)

end program Want2D


推荐答案

您正尝试使用 vector -下标(例如Fortran 2008,cl.6.5.3.3.2)。这使您可以使用向量(一维数组)从数组维​​度中选择随机元素。但是,这不能完全按照您打算从多个维度中选择一个元素的方式使用。

You are attempting to use a vector-subscript (e.g. Fortran 2008, cl. 6.5.3.3.2). This allows you to use a vector (1D array) to select random elements from an array dimension. This, however, cannot be used exactly as you intend it to select an element from multiple dimensions.

从6.5.3.3起(重点是我):

From 6.5.3.3 (emphasis mine):


> array-section ,其中具有 section-subscript-list ,该部分sub-中的每个 subscript-triplet vector-subscript
脚本列表指示下标序列,该下标可以为空。 此类序列中的每个下标均应在其维数范围内为
,除非序列为空。数组部分是
中元素的集合,该数组由所有可能的下标列表确定,这些列表可从每个部分下标指定的单个下标或下标
序列中获得。

In an array-section having a section-subscript-list, each subscript-triplet and vector-subscript in the section sub- script list indicates a sequence of subscripts, which may be empty. Each subscript in such a sequence shall be within the bounds for its dimension unless the sequence is empty. The array section is the set of elements from the array determined by all possible subscript lists obtainable from the single subscripts or sequences of subscripts specified by each section subscript.

如果您在示例代码中的目标是选择元素 a(5,3)和向量 b = [5,3] ,那么您可以更改您的写入方式

If you goal in your example code is to select the element a(5,3) with your vector b = [5, 3], then you could change your write from

write (*,*) a(b)           ! doesn't work

至:

write (*,*) a(b(1),b(2))   ! does work

您可以使用 b a 的每个维度使用1D截面,便可以获得较高级别的c $ c>。例如,如果 a 是5x5数组,则可以将 a 的角作为2x2数组,其内容如下: / p>

You can do more complicated array-sections with b of higher ranks as long as you use a 1D section for each dimension of a. For example if a is a 5x5 array, you could get the corners with of a as a 2x2 array with:

integer :: b(2,2)   ! 2 dimensional
b(1,:) = [1,5]
b(2,:) = [1,5]
write (*,*) a(b(1,:),b(2,:))   ! prints a(1,1), a(5,1), a(1,5), a(5,5)






在下面的注释中,您要求将其抽象为n维数组 a 。下面是一个我认为很丑陋的函数,因为它需要以我认为是骇客的方式使用c interop。您还需要更新的编译器才能使用该代码,因为它取决于 assumed-rank 数组。这是一个包含子例程的模块,该例程需要一个二维 b 包含要打印的数组索引和一个n维 a


In the comments below you requested that this be abstracted to an n-dimensional array a. Below is a function I consider ugly due to its need to use c interop in a way I consider a hack. You'll also need a newer compiler to even use the code, as it depends on assumed-rank arrays. Here is a module containing a subroutine that takes a 2-dimensional b containing array indices to print and an n-dimensional a to get the values from.

module future
  implicit none
contains
  subroutine print_array_vector(a, b)
    use, intrinsic :: iso_c_binding, only: c_loc, c_f_pointer
    implicit none
    integer, dimension(..), target :: a
    integer, dimension(:,:) :: b
    integer :: a_rank, b_len1
    integer, dimension(:,:,:), pointer :: a3 
    integer, dimension(:,:), pointer :: a2
    integer, dimension(:), pointer :: a1

    a_rank = rank(a)

    if (a_rank /= size(b,1)) then
       print *, "Rank mismatch between array and vector"
       return
    end if

    if (a_rank == 3) then
       call c_f_pointer(c_loc(a), a3, shape=[size(a,1), size(a,2), size(a,3)])
       print *, a3(b(1,:),b(2,:),b(3,:))
    else if (a_rank == 2) then
       call c_f_pointer(c_loc(a), a2, shape=[size(a,1), size(a,2)])
       print *, a2(b(1,:),b(2,:))
    else if (a_rank == 1) then
       call c_f_pointer(c_loc(a), a1, shape=[size(a,1)])
       print *, a1(b(1,:))
    else
       print *, "Unsupported rank"
       return
    end if
  end subroutine print_array_vector
end module future

这需要假定排名 a ,除了作为实际参数传递给C接口外,在Fortran中不能直接使用。但是,我们可以使用c-interop的其他部分来获取指向 a 的C指针,然后将其转换为适当形状的Fortran指针。现在我们有了可用形式的 a ,但是如果 / ,我们必须在内执行此操作else 块正确引用了不同的情况。我最多只实现了3维 a ,其余的部分留给读者练习。

This takes in assumed-rank a, which is not directly usable in Fortran except to pass as an actual argument to a C interface. However, we can use other parts of c-interop to get the C pointer to a, then turn it into a Fortran pointer of the appropriate shape. Now we have a in a usable form, but we have to do this within if/else blocks properly reference the different cases. I've only implemented up to 3-dimensional a, the rest is left as an exercise to the reader.

要使用此功能,请参见以下示例:

To use this function, here is an example:

program test
  use future
  implicit none
  integer :: a3(5,5,5), a2(5,5), a1(5)
  integer :: b3(3,2), b2(2,2), b1(1,2)
  integer :: i

  a3 = reshape([(i,i=1,125)],shape(a3))
  a2 = reshape([(i,i=1,25)],shape(a2))
  a1 = [(i,i=1,5)]

  b3 = reshape([1,1,1,5,5,5],shape(b3))
  b2 = reshape([1,1,5,5],shape(b2))
  b1 = reshape([1,5],shape(b1))

  call print_array_vector(a1,b1)
  call print_array_vector(a2,b2)
  call print_array_vector(a3,b3)
end program test

这将构造一个3-dim a 昏暗的 a 和一个1昏暗的 a ,以及几个2昏暗的 b 与数组的角的位置,然后我们调用函数以打印位置

This constructs a 3-dim a, a 2-dim a, and a 1-dim a, and a few 2-dim b's with the locations of the corners of the arrays and then we call the function to print the locations of the vector from the array.

% ./arraysection                           
           1           5
           1           5          21          25
           1           5          21          25         101         105         121         125

我使用gfortran 5.2编译并测试了该代码,我不知道其他版本的gfortran或其他Fortran编译器中对 assumed-rank 数组的当前支持状态。

I compiled and tested this with gfortran 5.2 and I have no idea the current state of support for assumed-rank arrays in other version of gfortran or in other Fortran compilers.

这篇关于使用向量访问N-D数组的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆