2010-03-25 71 views
8

Giả sử bạn có chức năng sau foo. Khi tôi chạy vòng lặp for, tôi muốn bỏ qua số còn lại của foo khi số foo trả về giá trị ban đầu là 0. Tuy nhiên, break không hoạt động khi bên trong một chức năng.vi phạm vòng lặp khi chạy một hàm bên trong vòng lặp for trong R

Vì văn bản hiện đang được viết, tôi nhận được thông báo lỗi, no loop to break from, jumping to top level.

Mọi đề xuất?

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

Cảm ơn tất cả mọi người cho ý kiến. Nhìn lại điều này, tôi nên thay đổi 'break' thành' next' vì điều đó sẽ phù hợp hơn với những gì tôi đang tìm kiếm. – andrewj

Trả lời

7

Phải thừa nhận rằng kiến ​​thức R của tôi là thưa thớt và điều này được drycoded, nhưng giống như sau nên làm việc:

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: cập nhật kiểm tra null cho hậu thế

+4

j == NULL không phải là một so sánh hợp lệ trong R (mặc dù có lẽ nó nên được). bạn cần is.null (j) –

+0

Cảm ơn! Đã cập nhật cho hậu thế. – Dusty

0

tôi không có đầu mối cách hoạt động của r nhưng tôi thấy câu hỏi thú vị vì tôi có thể tra cứu cú pháp của ngôn ngữ mới để giải thích câu trả lời của tôi nếu nó hoàn toàn sai :)

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 phải là y == 0. a == NULL phải là is.null (a). tiếp theo nên được phá vỡ. –

2

Một cách khác là để ném một lỗi và bắt nó với try, như vậy:

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, sử dụng ngoại lệ cho luồng điều khiển thực sự là biểu mẫu kém (chúng dành cho các điều kiện * ngoại lệ *, không phải hành vi mong đợi). –

+0

Không đồng ý. Trong một số ngôn ngữ, nó thậm chí còn được coi là hành vi thành ngữ (ví dụ: python). Dù bằng cách nào, chìa khóa là một số loại cờ cần phải được gửi từ foo() cho dù đó là một NULL, một ngoại lệ, hoặc bất cứ điều gì. – geoffjentry

4

Như một vấn đề của mã hóa thực tế, không làm điều này. Có một hàm chỉ có thể được sử dụng bên trong một vòng lặp cụ thể không phải là một ý tưởng tuyệt vời. Như một vấn đề quan tâm giáo dục, bạn có thể đánh giá 'break' trong môi trường cha mẹ.

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

Tôi nghĩ rằng nó là giá trị đặt một số hỗ trợ đằng sau "không làm điều này" và "vấn đề quan tâm giáo dục" điểm. :) – geoffjentry

+0

Yowser. Tôi xin thêm hỗ trợ cho điểm "không làm điều này"! =) –

+0

Tôi gần như mất niềm tin Tôi sẽ có thể xử lý nhiều loại lỗi trong hàm cao nhất của mình bằng cách cung cấp các đối số 'on.error1 = expression (action_on_error1)', 'on.error2 = ...' và cứ thế. Để có thể xử lý chúng bằng 'tryCatch (lower_lev_fun(), error = function (e) eval (on.error1))'. Trong trường hợp của tôi parent.frame (1) phát triển thành 'eval.parent (parse (text = 'next'), 7)', huh. Có vẻ như đó là cách duy nhất để làm cho lỗi xử lý như vậy chung chung. Cảm ơn! – jangorecki

4

Chúng tôi có được phép sáng tạo hơn một chút không? Bạn có thể giải quyết vấn đề của mình để tận dụng lợi thế của cách tiếp cận sau, nơi hoạt động dựa trên vectơ không?

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

Tuy nhiên, nếu một hình thức sâu hơn nền tảng cho các câu hỏi và chúng tôi cần phải làm theo mô hình này cho bây giờ, có lẽ tinh chỉnh nó chỉ là một chút ...

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 
    } 
} 
Các vấn đề liên quan