在一维数组中查找连续标志值的索引
Find the indices of a consecutive flag value in a 1D array
我想在一维数组中找到值 0。我在这个数组中有几个 0 值,大多数时候是连续的 0 值。现在我真正想要做的是找到每次连续出现的第一个零值出现和最后一个零值出现的索引,我将在下面举一个例子来使事情变得更清楚:
假设我有以下数组:
A= 0.0 0.0 0.0 0.0 0.0 0.0 0.38458693526004206 0.37630968444637147 0.40920888023862656 0.37240138383511134 0.38032672100490084 0.37013107455599198 0.40263333907360693 0.36804456033540955 0.41199172743738527 0.42761170349633443 0.39300715826673704 0.39783513932402137 0.44013743441396674 0.435127008833611 0.48217350280280391 0.47501246018014148 0.49234819258730078 0.54559998531569354 0.47840534103437832 0.0 0.0 0.0 0.51927791704510429 0.0 0.0 0.0 0.0 0.0 0.45862555500619961 0.50158980306905965 0.45676444815553296 0.49679306608627022 0.53878698007533210 0.50186256107128602 0.51714780706878094 0.53005606067091249 0.48409168179213419 0.48594430950932133 0.50963106475909081 0.49300327248076087 0.50531667704394834 0.46415085995913757 0.51930900041928330
所以我在每次连续出现时寻找零的第一个位置和最后一个位置,我应该得到以下内容:
min_loc_1=1
max_loc_1=6
min_loc_2=26
max_loc_2=28
min_loc_3=30
max_loc_3=34
现在我尝试了 any
、minloc
、maxloc
或 forall
的组合,但我无法弄清楚
do ijk = 1, size(work1)
if (work1(ijk) .eq. 0) then
location1(ijk) = ijk
end if
end do
min_loc=minloc(location1)
max_loc1=maxloc(location1)
我不能使用where
,因为我在其中调用了一个子程序,而 Fortran 显然不喜欢它。
有限的测试使我确信这可以解决您的紧迫问题。我还没有对其进行广泛的测试,我会把它留给你。它将 0
中每个 运行 的开始和结束索引写入数组 b
:
INTEGER, DIMENSION(:),ALLOCATABLE :: b
LOGICAL :: zz
...
ALLOCATE(b(0))
zz = .false.
DO ix = 1, SIZE(a)
IF (.NOT.zz.AND.a(ix)==0) THEN
b = [b,ix]
zz = .TRUE.
END IF
IF (zz.AND.a(ix)/=0) THEN
b = [b,ix-1]
zz = .FALSE.
END IF
END DO
当你向我们展示数组时,这会产生,
b == [1 6 26 28 30 34]
如果这没有吸引力,这似乎也有效:
b = [(ix,ix=1,SIZE(a))]
WHERE(a/=0.0) b = 0
c = PACK(b,b/=0)
b = PACK(c,(CSHIFT(c,1)-c)*(CSHIFT(c,-1)-c)/=-1)
如果您无法理解这个版本,请坚持使用第一个片段中的显式循环。
我想在一维数组中找到值 0。我在这个数组中有几个 0 值,大多数时候是连续的 0 值。现在我真正想要做的是找到每次连续出现的第一个零值出现和最后一个零值出现的索引,我将在下面举一个例子来使事情变得更清楚: 假设我有以下数组:
A= 0.0 0.0 0.0 0.0 0.0 0.0 0.38458693526004206 0.37630968444637147 0.40920888023862656 0.37240138383511134 0.38032672100490084 0.37013107455599198 0.40263333907360693 0.36804456033540955 0.41199172743738527 0.42761170349633443 0.39300715826673704 0.39783513932402137 0.44013743441396674 0.435127008833611 0.48217350280280391 0.47501246018014148 0.49234819258730078 0.54559998531569354 0.47840534103437832 0.0 0.0 0.0 0.51927791704510429 0.0 0.0 0.0 0.0 0.0 0.45862555500619961 0.50158980306905965 0.45676444815553296 0.49679306608627022 0.53878698007533210 0.50186256107128602 0.51714780706878094 0.53005606067091249 0.48409168179213419 0.48594430950932133 0.50963106475909081 0.49300327248076087 0.50531667704394834 0.46415085995913757 0.51930900041928330
所以我在每次连续出现时寻找零的第一个位置和最后一个位置,我应该得到以下内容:
min_loc_1=1
max_loc_1=6
min_loc_2=26
max_loc_2=28
min_loc_3=30
max_loc_3=34
现在我尝试了 any
、minloc
、maxloc
或 forall
的组合,但我无法弄清楚
do ijk = 1, size(work1)
if (work1(ijk) .eq. 0) then
location1(ijk) = ijk
end if
end do
min_loc=minloc(location1)
max_loc1=maxloc(location1)
我不能使用where
,因为我在其中调用了一个子程序,而 Fortran 显然不喜欢它。
有限的测试使我确信这可以解决您的紧迫问题。我还没有对其进行广泛的测试,我会把它留给你。它将 0
中每个 运行 的开始和结束索引写入数组 b
:
INTEGER, DIMENSION(:),ALLOCATABLE :: b
LOGICAL :: zz
...
ALLOCATE(b(0))
zz = .false.
DO ix = 1, SIZE(a)
IF (.NOT.zz.AND.a(ix)==0) THEN
b = [b,ix]
zz = .TRUE.
END IF
IF (zz.AND.a(ix)/=0) THEN
b = [b,ix-1]
zz = .FALSE.
END IF
END DO
当你向我们展示数组时,这会产生,
b == [1 6 26 28 30 34]
如果这没有吸引力,这似乎也有效:
b = [(ix,ix=1,SIZE(a))]
WHERE(a/=0.0) b = 0
c = PACK(b,b/=0)
b = PACK(c,(CSHIFT(c,1)-c)*(CSHIFT(c,-1)-c)/=-1)
如果您无法理解这个版本,请坚持使用第一个片段中的显式循环。