Один раз в R, т. Е. Оценивать только один оператор - PullRequest
0 голосов
/ 04 марта 2020

Я ищу метод в R для запуска блока внутри оператора if только в первый раз, когда оператор if оценивается как TRUE, но блок не будет запускаться снова, даже если условие if снова будет TRUE. В частности, этот метод будет полезен в al oop. Это будет оператор «один раз» (так называется на некоторых экзотических c языках).

Пример:

for (id in id_list){ # runs over a list of several id's which are random
   if (id == "snake"){ # I want to run this block only the first time and NOT each time id == "snake" 
      # now, do some calculations
      # ...
   }
   # do some other calculations by default for all other runs inside the loop
   # ...
}

Мне также было бы интересно узнать, как это будет работать в Python.

Ответы [ 2 ]

1 голос
/ 04 марта 2020

1) продублировано Используя тестовый ввод, показанный в первой строке, переберите индекс и добавьте условие, используя duplicated. Это позволяет избежать использования флага, что делает его менее подверженным ошибкам.

id_list <- c("a", "snake", "b", "snake") # test input

dup <- duplicated(id_list)
for(i in seq_along(id_list)) {
   if (id_list[i] == "snake" && (!dup)[i]) print("snake")
   print(i)
}

, дающий:

[1] 1
[1] "snake"
[1] 2
[1] 3
[1] 4

2) match Другой подход, позволяющий определить, какая итерация представляет первый экземпляр snake и использовать его в условии.

ix <- match("snake", id_list, nomatch = 0)
for(i in seq_along(id_list)) {
  if (i == ix) print("snake")
  print(i)
}

, дающий:

[1] 1
[1] "snake"
[1] 2
[1] 3
[1] 4

3) один раз

Другой подход заключается в создании функции once, которая возвращает значение TRUE первым время это бежит и ЛОЖЬ в противном случае. При этом используется изменяемая переменная x (аналогично флагу), но по крайней мере она инкапсулирована. Функция genOnce выводит функцию fre sh once.

Важно использовать && в условии, чтобы гарантировать, что правая часть && выполняется, только если левая сторона равна TRUE , & не имеет этого свойства короткого замыкания.

genOnce <- function(x = 0) function() (x <<- x + 1) == 1

once <- genOnce()
for(id in id_list) {
   if (id == "snake" && once()) print("***")
   print(id)
}

давая:

[1] "a"
[1] "***"
[1] "snake"
[1] "b"
[1] "snake"
0 голосов
/ 04 марта 2020

Предлагаемое решение с использованием глобальной переменной (т. Е. «Флага») для обозначения первого прохода в условии if:

first <- TRUE
for (i in 1:5) {
  if (first & i > 0) {
    print("run this block only the first time")
    first <- FALSE
  }
  print("do some other calculations")
}

Вывод:

[1] "run this block only the first time"
[1] "do some other calculations"
[1] "do some other calculations"
[1] "do some other calculations"
[1] "do some other calculations"
[1] "do some other calculations"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...