# Array of derived type: select entry

arraysderived-typesfortran

Currently in my code I have a 2D array

``````integer, allocatable :: elements(:,:)
``````

and define some constants

``````integer, parameter :: TYP = 1
integer, parameter :: WIDTH = 2
integer, parameter :: HEIGHT = 3
! ...
integer, parameter :: NUM_ENTRIES = 10
``````

and allocate something like

``````allocate(elements(NUM_ENTRIES,10000))
``````

so I can access elements like

``````write(*,*) elements(WIDTH,100) ! gives the width of the 100th element
``````

Now I would like to have not only integer but a mixture of types for every element.
So I define a derived type

``````type Element
logical active
integer type
real width
! etc
end type
``````

and use an array of Elements

``````type(Element), allocatable :: elements(:)
``````

With the 2d array version I could call a subroutine telling it which entry to use.
E.g.

``````subroutine find_average(entry, avg)
integer, intent(in) :: entry
real, intent(out) :: avg
integer i,
real s

s = 0
do i = lbound(elements,1), ubound(elements,1)
if (elements(TYP,i) .gt. 0) s = s + elements(entry,i)
end do
avg = s/(ubound(elements,1)-lbound(elements,1))
end subroutine
``````

So I could `call find_average(HEIGHT)` to find the average height or pass `WIDTH` to get the average width.
(And my subroutines do more advanced things than finding the average height or width, this is just an example.)

Question: How can I use different types (as with the derived type) but also reuse my functions to work with different entries (as in the example subroutine)?

#### Best Solution

For the array case, instead of passing in arguments array and index i, you could pass in the single argument array (i). When you switch to having the derived type, similarly you could pass in variable_of_type % element rather than passing in the entire variable_of_type and somehow instructing the procedure which subelement it is supposed to work on. If the code needs to be different for the different types of elements (e.g., logical, integer, real), then you could write specific procedures for each, but call then with a common name via a generic interface block. The compiler has to be able to distinguish the procedures of the generic interface block by some characteristic of the arguments, here their type. For a code example in which the distinguishing characteristic is array rank see how to write wrapper for 'allocate'

EDIT: example code. does this do what you want?

``````module my_subs

implicit none

interface my_sum
module procedure sum_real, sum_int
end interface my_sum

contains

subroutine sum_real (array, tot)
real, dimension(:), intent (in) :: array
real, intent (out) :: tot
integer :: i

tot = 1.0
do i=1, size (array)
tot = tot * array (i)
end do
end subroutine sum_real

subroutine sum_int (array, tot)
integer, dimension(:), intent (in) :: array
integer, intent (out) :: tot
integer :: i

tot = 0
do i=1, size (array)
tot = tot + array (i)
end do
end subroutine sum_int

end module my_subs

program test_dt

use my_subs

implicit none

type my_type
integer weight
real length
end type my_type

type (my_type), dimension (:), allocatable :: people

allocate (people (2))

people (1) % weight = 1
people (1) % length = 1.0
people (2) % weight = 2
people (2) % length = 2.0

call my_sum ( people (:) % weight, answer % weight )
write (*, *)  answer % weight

call my_sum ( people (:) % length, answer % length )
write (*, *)  answer % length

end program test_dt
``````