2010-03-25 20 views
8

Supponiamo di avere la seguente funzione foo. Quando eseguo il ciclo for, desidero che salti il ​​resto di foo quando foo restituisce inizialmente il valore di 0. Tuttavia, break non funziona quando è all'interno di una funzione.interruzione del ciclo for quando si esegue una funzione all'interno di un ciclo for in R

Come è attualmente scritto, ricevo un messaggio di errore, no loop to break from, jumping to top level.

Qualche suggerimento?

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

Grazie a tutti per i commenti. Ripensandoci, avrei dovuto cambiare 'break' in' next', dal momento che sarebbe stato più in linea con quello che stavo cercando. – andrewj

risposta

7

Certo la mia conoscenza R è scarsa e questo è drycoded, ma qualcosa di simile alla seguente dovrebbe funzionare:

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) 
} 

Edit: assegno nullo aggiornato per i posteri

+4

j == NULL non è un confronto valido in R (anche se forse dovrebbe essere). hai bisogno di is.null (j) –

+0

Grazie! Aggiornato per i posteri. – Dusty

0

non ho idea come funziona r ma ho trovato la domanda interessante perché ho potuto cercare la sintassi di una nuova lingua quindi scusami la mia risposta se è totalmente sbagliata :)

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 dovrebbe essere y == 0. a == NULL dovrebbe essere is.null (a). il prossimo dovrebbe essere interrotto. –

2

Un modo alternativo è quello di gettare un errore e prendere con try, in questo modo:

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, l'utilizzo di eccezioni per il controllo del flusso è una forma davvero scadente (sono per * condizioni * eccezionali, comportamento non previsto). –

+0

Non concordo. In alcuni linguaggi sarebbe anche considerato un comportamento idiomatico (ad esempio python). Ad ogni modo, la chiave è che una sorta di flag deve essere inviata da foo() che si tratti di un NULL, di un'eccezione o di qualsiasi altra cosa. – geoffjentry

4

È un dato di codifica pratica, non farlo. Avere una funzione che può essere utilizzata solo all'interno di un particolare ciclo non è una grande idea. Per quanto riguarda l'interesse educativo, puoi valutare la "rottura" nell'ambiente genitore.

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

Penso che valga la pena di mettere un po 'di sostegno dietro i punti "non fare questo" e "questione di interesse educativo". :) – geoffjentry

+0

Yowser. Con la presente aggiungo il supporto per il punto "non farlo"! =) –

+0

Ho quasi perso la fede Sarò in grado di gestire più tipi di errore nella mia funzione più elevata fornendo argomenti 'on.error1 = espressione (action_on_error1)', 'on.error2 = ...' e così via. Per poterli poi gestire con 'tryCatch (lower_lev_fun(), error = function (e) eval (on.error1))'. Nel mio caso parent.frame (1) evolve in 'eval.parent (parse (text = 'next'), 7)', huh. Sembra che sia l'unico modo per rendere la gestione degli errori così generica. Grazie! – jangorecki

4

Siamo autorizzati a essere un po 'più creativi? Puoi riformulare il tuo problema per sfruttare il seguente approccio, in cui l'operazione si basa sui vettori?

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

Se, tuttavia, una forma più profonda alla base della domanda e abbiamo bisogno di seguire questo schema per ora, forse modificarlo solo un po '...

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 
    } 
}