2010-03-25 2 views
8

Предположим, что у вас есть следующая функция: foo. Когда я запускаю цикл for, я бы хотел, чтобы он пропустил остаток от foo, когда foo сначала возвращает значение 0. Однако break не работает, когда он находится внутри функции.выход из цикла for при запуске функции внутри цикла for в R

Как написано в данный момент, появляется сообщение об ошибке no loop to break from, jumping to top level.

Любые предложения?

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

Спасибо всем за комментарии. Оглядываясь назад, я должен был изменить 'break' на' next', так как это было бы больше в соответствии с тем, что я искал. – andrewj

ответ

7

Правда мой R знание скудно и это drycoded, но что-то вроде должно работать:

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

редактирования: обновленный нулевой чек для потомков

+4

j == NULL не является допустимым сравнением в R (хотя, возможно, оно и должно быть). вам нужно is.null (j) –

+0

Спасибо! Обновлено для потомков. – Dusty

0

Я понятия не имею, как работает r, но я нашел вопрос интересным, потому что я мог искать синтаксис нового языка, поэтому извините мой ответ, если он полностью ошибается :)

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 должно быть y == 0. a == NULL должен быть is.null (a). следующий должен быть перерыв. –

2

Альтернативный способ бросить ошибку и поймать его с try, например, так:

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, использование исключений для потока управления действительно плохое (они предназначены для * исключительных условий, а не ожидаемого поведения). –

+0

Не согласен. На некоторых языках он даже рассматривался как идиоматическое поведение (например, python). В любом случае, ключ заключается в том, что какой-то флаг нужно отправлять из foo(), будь то NULL, исключение или что-то еще. – geoffjentry

4

По сути кодирования практики, не делают этого. Наличие функции, которая может использоваться только внутри конкретного цикла, не является отличной идеей. Что касается образовательного интереса, вы можете оценить «разрыв» в родительской среде.

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

Я думаю, что стоит пожертвовать поддержкой «не делай этого» и «вопрос интереса к образованию». :) – geoffjentry

+0

Yowser. Я тем самым добавляю поддержку «не делай этого»! =) –

+0

Я почти потерял веру. Я смогу обрабатывать несколько типов ошибок в своей наивысшей функции, предоставляя аргументы 'on.error1 = expression (action_on_error1)', 'on.error2 = ...' и так далее. Чтобы впоследствии обработать их с помощью 'tryCatch (lower_lev_fun(), error = function (e) eval (on.error1))'. В моем случае parent.frame (1) развивается до 'eval.parent (parse (text = 'next'), 7)', huh. Кажется, что это единственный способ сделать обработку ошибок такой общей. Благодаря! – jangorecki

4

Можем ли мы быть более креативными? Не могли бы вы переделать свою проблему, чтобы воспользоваться следующим подходом, где операция основана на векторах?

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

Если, однако, более глубокая форма лежит в основе вопроса, и мы должны следовать этому образцу сейчас, возможно, настроить его только немного ...

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 
    } 
} 
Смежные вопросы