【问题标题】:Once statement in R i.e. evaluate if statement only onceR中的Once语句,即只评估一次if语句
【发布时间】:2020-03-05 00:20:21
【问题描述】:

我正在 R 中寻找一种方法,仅在 if 语句第一次被评估为 TRUE 时在 if 语句中运行块,但即使 if 条件再次为 TRUE,该块也不会再次运行。具体来说,该方法在循环中很有用。 这将是“once”语句(在某些外来语言中如此称呼)。

例子:

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 中是如何工作的。

【问题讨论】:

  • A {break} 会中断循环,但这不是所需的行为,因为应该为所有 id 执行 if 块之外的部分——即使在评估第一个 TRUE 之后也是如此。

标签: r if-statement


【解决方案1】:

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) 匹配 另一种方法来确定哪个迭代代表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,否则返回 FALSE。这确实使用了一个可变变量x(类似于标志),但至少它是被封装的。 genOnce 函数输出一个新的 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"

【讨论】:

    【解决方案2】:

    使用“全局”变量(即“标志”)表示首先传入 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"
    

    【讨论】:

    • 感谢@dario,这似乎是一个可行的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 2018-10-14
    • 1970-01-01
    相关资源
    最近更新 更多