fortran 在数组中找到一系列整数

fortran find series of integers in array

Fortran 中是否有函数或方法来查找数组中的一系列整数和 return 数组中的位置或如果匹配则计数?

(1, 5, 8, 56, 33, 56, 78, 123, 78, 8, 34, 33, 19, 25, 36)

找到 (8,56,33)

return3 作为位置或 1 作为匹配项

如果是多个:

(1, 5, 8, 56, 33, 56, 78, 123, 78, 8, 56, 33, 19, 25, 36)

找到 (8,56,33)

Return 3 和 10 或 2

fortran 中是否有处理这种数组搜索的函数?

简短的回答是 "No",Fortran 中没有这样的 intrinsic 函数。

通常期望您自己编写这样的内容。例如:

  • 从所有可能的起始索引数组开始
  • 确定保留索引的条件
  • 依次只保留满足条件的索引

内在过程pack在这里非常有用,它可用于仅保留数组(您的起始位置)中符合特定条件(您保留起始位置的条件)的值。

下面的(未经过广泛测试!)程序 "test.f90" 说明了用法:

module mod_finder
    implicit none

    contains
        subroutine find_start_locs(array, sub_array, start_locs)
            integer, intent(in) :: array(:)
            integer, intent(in) :: sub_array(:)
            integer, allocatable, intent(out) :: start_locs(:)
            integer :: i

            ! initialize result with all possible starting indices
            start_locs = [(i, i = 1, size(array)-size(sub_array)+1)]

            ! sequentially keep only those indices that satisfy a condition
            do i = 1, size(sub_array)
                ! condition for keeping: the value of array(start_locs + i - 1) must be equal to the value of sub_array(i)
                ! use PACK to only keep start_locs that satisfy this condition
                start_locs = PACK(start_locs, array(start_locs + i - 1) == sub_array(i))
                if (size(start_locs) == 0) then
                    exit
                end if
            end do
        end subroutine find_start_locs

end module mod_finder

program test
    use mod_finder
    implicit none

    integer, allocatable :: arr(:)
    integer, allocatable :: seq(:)
    integer, allocatable :: res(:)

    ! arr = [1, 5, 8, 56, 33, 56, 78, 123, 78, 8, 34, 33, 19, 25, 36]
    arr = [1, 5, 8, 56, 33, 56, 78, 123, 78, 8, 56, 33, 19, 25, 36]
    seq = [8, 56, 33]

    call find_start_locs(arr, seq, res)

    print *, "array:     ", arr
    print *, "sequence:  ", seq
    print *, "locations: ", res
    print *, "# matches: ", size(res)

end program test

对于你问题中的两个测试用例,编译和运行给出以下输出:

$ gfortran -O2 -g -Wall -Wextra -fcheck=all test.f90
$ ./a.out

 array:                1           5           8          56          33          56          78         123          78           8          34          33          19          25          36
 sequence:             8          56          33
 locations:            3
 # matches:            1

 array:                1           5           8          56          33          56          78         123          78           8          56          33          19          25          36
 sequence:             8          56          33
 locations:            3          10
 # matches:            2

您所追求的是一种叫做滑动window 搜索算法的东西。一个简单的实现如下:

program test
  implicit none

  integer, dimension(:), allocatable :: arr 
  integer, dimension(:), allocatable :: seq
  integer                            :: i

  arr = [1, 5, 8, 56, 33, 56, 78, 123, 78, 8, 56, 33, 19, 25, 36]
  seq = [8, 56, 33]

  do i=1,size(arr)-size(seq)+1
     if (all(arr(i:i+size(seq)-1) == seq)) print *, i
  end do
end program

这不是最优化的版本,但在大多数情况下都能胜任。