【问题标题】:Selecting all elements from a fortran array except one从 fortran 数组中选择除一个之外的所有元素
【发布时间】:2020-06-18 00:27:15
【问题描述】:

假设我有一个一维数组,例如 A(1:10),我想对该数组的所有元素进行操作,除了第 3 个元素(比方说)。如何在执行操作时跳过此元素? A(1:10)=2*A(1:10) 会将这个数组的所有元素乘以 2,但假设我不想将第三个元素乘以 2。我该如何在 Fortran 中做到这一点?

【问题讨论】:

  • 在这种特殊情况下,我会这样做:A=2*A; A(3)=A(3)/2

标签: fortran


【解决方案1】:

正如其他回复所指出的,有几种方法可以实现这一点,但我最喜欢的选项尚未列出,即使用FORALL 声明:

forall (i=1:10,i/=3) A(i)=2*A(i)

出于某种原因,这在 Fortran 2018 中已过时,但我相信这是获得所需内容的最清晰、简洁和可矢量化的方式。

另一种简洁的方法是,如果您将纯数组索引函数存储在其他地方,例如:

pure function arrayI(n) result(indices)
   integer, intent(in) :: n
   integer :: indices(n),i   
   forall(i=1:n) indices(i)=i
end function arrayI

然后用一行代码解决你的问题

where (arrayI(10)/=3) a=2*a

【讨论】:

  • 关于删除for all 的一些原因,请参阅stackoverflow.com/questions/8602596/fortran-forall-restrictions 以及它指向您的一些参考资料。现在很多人更喜欢do concurrent,它没有for all 的问题。
  • 感谢@HighPerformanceMark 的链接 - 是的,看起来这个决定是基于编译器性能,但对我来说,使代码尽可能短非常重要,尤其是在处理大型项目时。 Fortran 90/95 非常擅长它所有的“Matlab 风格”语法,你可以在一行中得到很多,我仍然认为没有更好的语言。从可读性的角度来看,现代 Fortran 更糟糕,它的所有 %s 和 very%long%variable%names ....
【解决方案2】:

Fortran 中没有基本操作可以根据排除标准选择数组的特定元素集。但是,有几种方法可用,但工作量更大。

如果可以构造一个包含所需索引的数组,则可以使用向量下标

integer a(10)
integer, allocatable :: idx(:)

idx = [...]  ! An array constructor of the desired elements to select
a(idx) = 2*a(idx)

对于问题的情况,这样的数组构造函数很可能是idx=[1,(i,i=3,10)]。我们可以在很多语句中建立这个数组,甚至不用变量作为向量下标。

我们可以使用 WHERE 构造来选择要作用于数组的元素

integer a(10), i
a = 1
where ([(i,i=1,10)]/=2)  ! Or other selecting expression
  a = 2*a
end where

(对于标记为 Fortran 90,请改用数组构造函数 (/(...)/)。)

还有一些围绕数组部分的方法(如 Tine198 的回答),或者只是在循环中使用排除:

do i=1, 10
   if (i==2) cycle ! Or other element exclusion criterion
   a(i) = 2*a(i)
end do

【讨论】:

  • 非常感谢您的建议。我很清楚你建议的上述方法。实际上,我选择的示例非常简单,实际过程涉及对数组的几个不同元素执行大量计算,该数组基本上是一个 6D 数组。我只是想知道 Fortran 中是否有这样的功能可以让我们根据需要对数组进行切片。
【解决方案3】:

如果它只是一个元素,你可以先将它保存到另一个变量中,然后在操作后重写它的值:

backup=A(i)
A=2*A
A(i)=backup

另一种选择是明确排除它

A(:i-1)=2*A(:i-1)
A(i+1:)=2*A(i+1:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-24
    • 2013-11-04
    • 2010-09-15
    • 2017-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多