2010-03-25 9 views
8

Suponga que tiene la siguiente función foo. Cuando estoy ejecutando un bucle for, me gustaría omitir el resto de foo cuando foo inicialmente devuelve el valor de 0. Sin embargo, break no funciona cuando está dentro de una función.ruptura del bucle for cuando se ejecuta una función dentro de un bucle for en R

Como está actualmente escrito, recibo un mensaje de error, no loop to break from, jumping to top level.

¿Alguna sugerencia?

foo <- function(x) { 
    y <- x-2 
    if (y==0) {break} # how do I tell the for loop to skip this 
    z <- y + 100 
    z 
} 


for (i in 1:3) { 
    print(foo(i)) 
} 
+0

Gracias a todos por los comentarios. Mirando hacia atrás en esto, debería haber cambiado 'break' por' next' ya que eso habría estado más en línea con lo que estaba buscando. – andrewj

Respuesta

7

Es cierto que mi conocimiento R es escasa y esto se drycoded, sino algo así como lo siguiente debería funcionar:

foo <- function(x) { 
    y <- x-2 
    if (y==0) {return(NULL)} # return NULL then check for it 
    z <- y + 100 
    z 
} 

for (i in 1:3) { 
    j <- foo(i) 
    if(is.null(j)) {break} 
    print(j) 
} 

Editar: cheque nulo actualizado para la posteridad

+4

j == NULL no es una comparación válida en R (aunque tal vez debería ser). necesitas is.null (j) –

+0

¡Gracias! Actualizado para la posteridad. – Dusty

0

no tengo idea cómo funciona r pero encontré la pregunta interesante porque podía buscar la sintaxis de un nuevo idioma, así que perdona mi respuesta si es totalmente errónea :)

foo <- function(x) { 
    y <- x-2 
    if (y!=0) z <- NULL else z <- y + 100 
    z 
} 


for (i in 1:3) 
{ 
    a <- foo(i) 
    if (a == NULL) {next} 
    print(a) 
} 
+0

y! = 0 debería ser y == 0. a == NULL debe ser is.null (a). el próximo debería ser descanso. –

2

Una forma alternativa es tirar un error y atraparla con try, así:

foo <- function(x) { 
    y <- x-2 
    if (y==0) {stop("y==0")} 
    z <- y + 100 
    z 
} 

try(for (i in 0:5) { 
     print(foo(i)) 
}, silent=TRUE) 

## or use tryCatch: 
for (i in 0:5) { 
    bar <- tryCatch(foo(i),error=function(e) NA) 
    if(is.na(bar)){ break } else { print(bar) } 
} 
+1

-1, el uso de excepciones para el flujo de control es muy pobre (son para condiciones * excepcionales *, comportamiento no esperado). –

+0

No estoy de acuerdo. En algunos idiomas, incluso se consideraría un comportamiento idiomático (por ejemplo, pitón). De cualquier manera, la clave es que se debe enviar algún tipo de señal desde foo() ya sea un NULL, una excepción o lo que sea. – geoffjentry

4

Como cuestión de práctica de codificación, no hagas esto. Tener una función que solo se puede usar dentro de un bucle en particular no es una gran idea. Como cuestión de interés educativo, puede evaluar el "descanso" en el entorno principal.

foo <- function(x) { 
    y <- x-2 
    if (y==0) {eval.parent(parse(text="break"),1)} 
    z <- y + 100 
    z 
} 



for (i in 0:3) { 
    print(foo(i)) 
} 
+4

Creo que vale la pena respaldar los puntos de "no hacer esto" y "asunto de interés educativo". :) – geoffjentry

+0

Yowser. Por la presente, agrego soporte para el punto "no hagas esto"! =) –

+0

Casi pierdo la fe. Seré capaz de manejar múltiples tipos de error en mi función más alta al proporcionar argumentos 'on.error1 = expression (action_on_error1)', 'on.error2 = ...' y así sucesivamente. Para poder manejarlos más tarde por 'tryCatch (lower_lev_fun(), error = function (e) eval (on.error1))'. En mi caso parent.frame (1) evoluciona a 'eval.parent (parse (text = 'next'), 7)', huh. Parece que es la única forma de hacer que el manejo de errores sea tan genérico. ¡Gracias! – jangorecki

4

¿Se nos permite ser un poco más creativos? ¿Podría reformular su problema para aprovechar el siguiente enfoque, donde la operación se basa en vectores?

x <- 1:3 
y <- x[x-2 < 0] - 2 + 100 # I'm leaving the "- 2" separate to highlight the parallel to your code 
y 

Si, sin embargo, una forma más profunda subyace la cuestión y tenemos que seguir este patrón, por ahora, tal vez retocarlo un poco ...

foo <- function(x) { 
    y <- x - 2 
    if (y != 0) { 
    z <- y + 100 
    z 
    } # else implicitly return value is NULL 
} 

for (i in 1:3) { 
    if (is.numeric(result <- foo(i))) { 
    print(result) 
    } else { 
    break 
    } 
}