Выбор всех элементов из массива fortran, кроме одного - PullRequest
0 голосов
/ 08 мая 2020

Предположим, у меня есть одномерный массив, например, A (1:10), и я хочу выполнить операцию со всеми элементами этого массива, кроме 3-го элемента (скажем). Как я могу пропустить этот элемент при выполнении операции? A (1:10) = 2 * A (1:10) умножит все элементы этого массива на 2, но предположим, что я не хочу умножать 3-й элемент на 2. Как мне это сделать в Фортране?

Ответы [ 3 ]

1 голос
/ 08 мая 2020

В Фортране нет основной операции c, которая предписывала бы выбрать определенный набор элементов массива на основе критерия исключения. Однако существует несколько подходов, требующих более сложных усилий.

Если можно построить массив желаемых индексов для включения, то можно использовать векторные индексы

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) или просто с использованием исключения в al oop:

do i=1, 10
   if (i==2) cycle ! Or other element exclusion criterion
   a(i) = 2*a(i)
end do
0 голосов
/ 17 июня 2020

Как указывали другие ответы, есть несколько способов выполнить sh этого, но вариант, который мне больше всего нравится, не указан, то есть с помощью оператора 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
0 голосов
/ 08 мая 2020

Если это всего лишь один элемент, вы можете сначала сохранить его в другую переменную, а затем переписать его значение после операции:

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

другой вариант - явно исключить его

A(:i-1)=2*A(:i-1)
A(i+1:)=2*A(i+1:)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...