forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Find values satsfying condition in array

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General
View previous topic :: View next topic  
Author Message
arctica



Joined: 10 Sep 2006
Posts: 105
Location: United Kingdom

PostPosted: Wed Jan 17, 2024 2:55 pm    Post subject: Find values satsfying condition in array Reply with quote

Hello

Is there a way to find the indices in array where a condition is satisfied and then extract those values. The equivalent in Matlab/Scilab:

values = x(find(x > 4.7)) where x is an array of real or integer values.

Pretty sure it must revolve around the use of findloc, but an example would be useful.

Thanks

Lester
Back to top
View user's profile Send private message
arctica



Joined: 10 Sep 2006
Posts: 105
Location: United Kingdom

PostPosted: Wed Jan 17, 2024 4:22 pm    Post subject: Reply with quote

This will work, but cannot figure out how the same can be done via findloc:

Code:

program FindValuesGreaterThan2
  implicit none
  integer, parameter :: n = 10
  real :: testArray(n)
  integer :: indices(n)
  real, dimension(:), allocatable :: newArray
  integer :: count, i

  ! Initialize the test array with some values
  testArray = [1.0, 3.0, 2.0, 5.0, 0.0, 4.0, 2.5, 6.0, 1.5, 3.5]

  ! Find indices where values are greater than 2
  indices = 0  ! Initialize indices array with zeros
  count = 0    ! Initialize count

  do i = 1, n
    if (testArray(i) > 2.0) then
      count = count + 1
      indices(count) = i
    end if
  end do

  ! Allocate memory for the new array
  allocate(newArray(count))

  ! Extract values greater than 2 to the new array
  do i = 1, count
    newArray(i) = testArray(indices(i))
  end do

  ! Print the original and new arrays
  print *, 'Original array:', testArray
  print *, 'Values greater than 2:', newArray

  ! Deallocate the memory
  deallocate(newArray)

end program FindValuesGreaterThan2
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Wed Jan 17, 2024 6:10 pm    Post subject: Reply with quote

There are a number of intrinsic functions that operate on arrays, such as PACK, MERGE, etc., whose purpose is to perform operations of the type sought.

Code:
program FindValuesGreaterThan2
  implicit none
  integer, parameter :: n = 10
  real :: testArray(n)
  integer :: indices(n)
  integer :: i, nsel
  integer, allocatable :: selIdx(:)

  ! Initialize the test array with some values
  testArray = [1.0, 3.0, 2.0, 5.0, 0.0, 4.0, 2.5, 6.0, 1.5, 3.5]
  indices = [(i,i=1,n)]
  ! Select and list elements > 4.7
  selIdx = pack(indices,testArray > 4.7)
  nsel = size(selIdx)
  print '(1x,2i3,F4.1)',(i,selIdx(i),testArray(selIdx(i)),i=1,nsel)

end program FindValuesGreaterThan2


Last edited by mecej4 on Fri Jan 19, 2024 2:51 am; edited 3 times in total
Back to top
View user's profile Send private message
arctica



Joined: 10 Sep 2006
Posts: 105
Location: United Kingdom

PostPosted: Thu Jan 18, 2024 3:24 pm    Post subject: Reply with quote

Many thanks for the suggestion and syntax example.
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Fri Jan 19, 2024 1:17 am    Post subject: Reply with quote

mecej4,

Did you compile your example before posting ?
looks like you didn't, so not bad for no checking.

Here is my (tested) example showing mecej4's new F90 way and mine and (Eddie's?) old way using DO loops.

Code:
program FindValuesGreaterThan2
 
  integer, parameter :: n = 10
  real :: testArray(n)
  testArray = [1.0, 3.0, 2.0, 5.0, 0.0, 4.0, 2.5, 6.0, 1.5, 3.5]

  call old_DO_way ( testArray,n )
  call new_pack_way ( testArray,n )
end program FindValuesGreaterThan2
 
subroutine new_pack_way ( testArray,n )
    implicit none
  integer :: n
  real :: testArray(n)
  integer :: indices(n)
  integer :: nsel, i
  integer, allocatable :: selIdx(:)

  ! Initialize the test array index
  indices = [(i,i=1,n)]
  ! Select and list elements > 4.7
  selIdx = pack(indices,testArray > 4.7)
  nsel = size(selIdx)

  print '(1x,2i3,F4.1)',(i,selIdx(i),testArray(selIdx(i)),i=1,nsel)

end subroutine new_pack_way

SUBROUTINE old_DO_way  ( testArray,n )
  implicit none
  integer :: n
  real :: testArray(n)
  integer :: nsel, i
  integer :: selIdx(n)

  ! generate a list of values
  nsel = 0
  do i = 1,n
    if ( testArray(i) <= 4.7 ) cycle
    nsel = nsel+1
    selIdx(nsel) = i
  end do

  print '(1x,2i3,F4.1)',(i,selIdx(i),testArray(selIdx(i)),i=1,nsel)

end SUBROUTINE old_DO_way


I still prefer to see DO loops to show what is happening.
After these comments, I hope my code doesn't need correcting !
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Fri Jan 19, 2024 4:12 am    Post subject: Reply with quote

Lester, you may wish to read Chapter 2 of Arjen Markus's book, Modern Fortran in Practice, https://books.google.com/books?id=pOH80J24R_gC&printsec=copyright#v=onepage&q=pack&f=false , where he gives several examples of expressing calculations compactly using arrays and array manipulation functions.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group