2010-03-25 7 views
8

Supposons que vous ayez la fonction foo suivante. Lorsque je cours une boucle for, je voudrais passer le reste de foo lorsque foo retourne initialement la valeur de 0. Cependant, break ne fonctionne pas lorsqu'il se trouve dans une fonction.rupture de la boucle for lors de l'exécution d'une fonction dans une boucle for R

Comme il est actuellement écrit, j'obtiens un message d'erreur, no loop to break from, jumping to top level.

Des suggestions?

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

Merci à tous pour les commentaires. En regardant en arrière, j'aurais dû changer 'break'' next' car cela aurait été plus conforme à ce que je cherchais. – andrewj

Répondre

7

Il est vrai que ma connaissance R est rare et cela est drycoded, mais quelque chose comme ce qui suit devrait fonctionner:

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: vérification null mis à jour pour la postérité

+4

j == NULL n'est pas une comparaison valide dans R (bien que ce devrait être le cas). Vous avez besoin de is.null (j) –

+0

Merci! Mis à jour pour la postérité. – Dusty

0

Je n'ai pas la moindre idée comment fonctionne r mais j'ai trouvé la question intéressante parce que je pourrais chercher la syntaxe d'une nouvelle langue alors excusez ma réponse si elle est totalement fausse :)

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 devrait être y == 0. a == NULL devrait être is.null (a). la prochaine devrait être pause. –

2

Une autre façon est de jeter une erreur et l'attraper avec try, comme ceci:

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, en utilisant des exceptions pour le flux de contrôle est vraiment de mauvaise forme (ils sont pour des conditions * exceptionnelles *, pas de comportement attendu). –

+0

En désaccord. Dans certaines langues, il serait même considéré comme un comportement idiomatique (par exemple python). D'une manière ou d'une autre, la clé est qu'une sorte de drapeau doit être envoyé par foo() que ce soit une valeur NULL, une exception ou autre. – geoffjentry

4

En pratique le codage, ne le faites pas. Avoir une fonction qui ne peut être utilisée qu'à l'intérieur d'une boucle particulière n'est pas une bonne idée. Pour des raisons d'éducation, vous pouvez évaluer la «rupture» dans l'environnement parent.

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

Je pense que cela vaut la peine de soutenir les points «ne fais pas ça» et «question d'intérêt éducatif». :) – geoffjentry

+0

Yowser. Par la présente, j'appuie le point "ne fais pas ça"! =) –

+0

J'ai presque perdu la foi Je serai capable de gérer plusieurs types d'erreurs dans ma fonction la plus élevée en fournissant des arguments 'on.error1 = expression (action_on_error1)', 'on.error2 = ...' et ainsi de suite. Pour pouvoir ensuite les manipuler par 'tryCatch (lower_lev_fun(), error = fonction (e) eval (on.error1))'. Dans mon cas, parent.frame (1) évolue vers 'eval.parent (parse (text = 'next'), 7)', hein. Il semble que ce soit la seule façon de rendre la gestion des erreurs si générique. Merci! – jangorecki

4

Sommes-nous autorisés à être un peu plus créatif? Pourriez-vous reformuler votre problème pour tirer parti de l'approche suivante, où l'opération est basée sur des vecteurs?

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, cependant, une forme plus profonde sous-tend la question et nous devons suivre ce modèle pour l'instant, peut-être ruser un peu ...

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