在R中的do-while循环

75

我想知道如何编写do-while风格的循环。

我找到了这篇帖子

你可以使用repeat{},并在任何需要使用if()的地方检查条件,并使用“break”控制词退出循环。

我不确定它确切的意思是什么。如果您理解并且有不同的解决方法,请详细说明一下?


2
@Jericho和@DWin的答案之间的区别在于“语句”是否被评估。在@Jericho的答案中,循环至少运行一次,因为break条件在“语句”之后。在@DWin的答案中,如果y最初大于或等于5,则循环根本不会运行。您喜欢哪个取决于您是否想要运行“语句”。 - Gavin Simpson
总之,do while语句会在至少执行一次后检查条件,然后返回到语句循环。 - A Salcedo
因此,如果您确保在循环之前将条件设置为true(例如,使用临时变量和or连接符或其他方法),则可以使用while循环而不是do-while循环来运行循环(语句)至少一次,就像Dwin的回答中所示。 - Henrik
4个回答

143
相当简单明了。
repeat{
  statements...
  if(condition){
    break
  }
}

我认为应该是类似于这样。为了获得do while循环的效果,只需在语句组的末尾检查条件。


这比使用while更快吗? - Emer
4
while和do-while用于不同的情况。可以这样理解,while表示执行0到多次,而do-while表示执行1到多次。我认为它们并不是更快或更慢,只是有时你希望至少执行一次,有时则不需要。这只是条件放置的区别。 - A Salcedo
2
对我来说,42的答案是正确的,而Salcedo的答案是错误的。在42的答案中,条件语句中有一个否定词(repeat( { expressions}; if (! end_cond_expr ) {break} ))。因此,使用repeat !EndCondition可以模拟do-while EndCondition。我通过代码片段验证了这个事实。 - Erdogan CEVHER
1
@ErdoganCEVHER OP没有定义condition的含义,所以我不会说Salcedo的答案是错误的。但你说得很对,if(!condition){break}更符合C语言的do{} while(condition)结构。 - Josiah Yoder

33

请查看?Control或者R语言定义:

> y=0
> while(y <5){ print( y<-y+1) }
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

do_while 在 R 中并不存在作为一个单独的结构,但您可以使用以下方法模拟实现:

repeat( { expressions}; if (! end_cond_expr ) {break} )
如果您想查看帮助页面,您不能在控制台中输入?while?repeat,而是需要使用?'repeat'?'while'。 所有的"控制结构",包括if都在同一页上,并且所有需要在“?”后引用字符,这样解释器才不会将其视为不完整的代码并给出续行符“+”。

3
这是"while-do",而不是所要求的"do-while"。关键在于"do-while"设置将让您在一个地方编写一些命令(而非在循环块内外重复编写),并保证调用预期的函数一次。就像在这个答案中,您会看到有两行代码将一个值赋给y (第一行和print调用内部)。为了减少冗余并减少某些情况下出现错误的可能性,使用"do-while"很好,因此您只需赋值给某个变量(例如y)一次即可。 - Kalin
1
关键在于终止条件何时(以及如何)执行。在do-while循环中,在每次迭代之前测试条件是否为真,而在repeat-until循环中,则在迭代结束时进行测试,并在看到TRUE值时退出。 - IRTFM
1
与语言差异无关,而是控制流程的差异。do-while 的意思是:运行此代码块一次。检查条件。如果条件为假,则再次运行此代码块。重复检查条件。while 的意思是:检查条件。运行此代码块。如果条件为假,则再次运行此代码块。重复检查条件。在 do-while 循环中,条件在代码执行后进行检查。在 while 循环中,条件在代码执行前进行检查。在 do-while 循环中,保证至少执行一次代码。在 while 循环中,代码可能永远不会被执行。 - cazgp
没错。我明白了你想表达的区别。在 R 中没有 do_while,所以要获得这种行为,需要使用 repeat {expr},其中 expr 在末尾有一个测试和一个 break,或者使用 Henrik 在评论中建议的策略。 - IRTFM
对我来说,42的答案是正确的,而Salcedo的答案是错误的。在42的答案中,条件中有一个否定(repeat( { expressions}; if (! end_cond_expr ) {break} ))。因此,使用repeat !EndCondition模拟do-while EndCondition。当我将高斯代码转换为R时,我应用了42的逻辑,并且加上否定符号救了我的命。非常感谢42。 - Erdogan CEVHER
显示剩余4条评论

7

在其他答案的基础上,我想分享一个使用while循环结构实现do-while行为的示例。通过在while条件中使用一个简单的布尔变量(初始化为TRUE),然后在if语句中稍后检查我们的实际条件。也可以在if语句中使用break关键字而不是continue <- FALSE(可能更有效率)。

  df <- data.frame(X=c(), R=c())  
  x <- x0
  continue <- TRUE

  while(continue)
  {
    xi <- (11 * x) %% 16
    df <- rbind(df, data.frame(X=x, R=xi))
    x <- xi

    if(xi == x0)
    {
      continue <- FALSE
    }
  }

2
注意到用户42-'s的完美方法:{
* "do while" = "repeat until not"
* 代码等价性:

do while (condition) # in other language
..statements..
endo

repeat{ # in R
  ..statements..
  if(! condition){ break } # Negation is crucial here!
}

如果某人在do-while循环中不通过!或否定条件来取消条件,则代码执行的过程中可能存在扭曲的情况(1. 值持久化 2. 无限循环)。因此,我将通过一个具体的例子强调并突出他的方法。在高斯中: } 没有得到足够的关注。
proc(0)=printvalues(y);
DO WHILE y < 5;    
y+1;
 y=y+1;
ENDO;
ENDP;
printvalues(0); @ run selected code via F4 to get the following @
       1.0000000 
       2.0000000 
       3.0000000 
       4.0000000 
       5.0000000 

在R中:

printvalues <- function(y) {
repeat {
 y=y+1;
print(y)
if (! (y < 5) ) {break}   # Negation is crucial here!
}
}
printvalues(0)
# [1] 1
# [1] 2
# [1] 3
# [1] 4
# [1] 5

我仍然坚持认为,在do-while中没有否定条件的情况下,Salcedo的答案是错误的。可以通过在上述代码中删除否定符号来检查这一点。

2
我认为你误解了Salcedo的回答。伪代码中没有明确的条件。你可以用!(y<5)替换他的(condition),或者用(y>=5)或其他你需要的条件来替换它,以满足使用情况。它不一定要有否定符号,只要你需要逻辑条件来停止循环即可。 - matt
不,我没有误解。我强调的是在do-while中必须使用指定条件的“否定”。在数学上,“!(y<5)”和“(y>=5)”是等价的。两者都是否定了“(y<5)”。我并不坚持使用“!”否定符号。一个人可以将否定符号分配给手头的短语,就像!(y<5)= (y>=5)一样。 - Erdogan CEVHER

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接