【问题标题】:fortran find series of integers in arrayfortran 在数组中查找整数系列
【发布时间】:2020-01-18 23:25:27
【问题描述】:

Fortran 中是否有函数或方法可以在数组中查找整数序列并返回数组中的位置或在匹配时进行计数?

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

找到 (8,56,33)

返回 3 作为位置或 1 作为匹配项

如果有多个:

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

找到 (8,56,33)

返回 3 和 10 或 2

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

【问题讨论】:

标签: fortran fortran90 fortran95


【解决方案1】:

简短的回答是“否”,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

【讨论】:

  • 如果您正在处理大型数组,您可能需要修改find_start_locs 子例程以使用@kvantour's answer 中概述的方法来建立 start_locs 而不是像我一样剥离。除了初始开销之外,我在pack 中的条件掩码需要访问array 的非连续元素,而滑动窗口更连续地访问元素
【解决方案2】:

您所追求的是一种称为滑动窗口搜索算法的东西。一个简单的实现如下:

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

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

【讨论】:

    猜你喜欢
    • 2014-02-14
    • 2023-04-09
    • 1970-01-01
    • 2016-11-18
    • 2015-07-26
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    相关资源
    最近更新 更多