Như đã được lưu ý, vapply
hai điều:
- Cải thiện tốc độ nhẹ
- Cải thiện tính nhất quán bằng cách cung cấp kiểm tra loại trả lại hạn chế.
Điểm thứ hai là lợi thế lớn hơn, vì nó giúp bắt lỗi trước khi chúng xảy ra và dẫn đến mã mạnh hơn. Việc kiểm tra giá trị trả về này có thể được thực hiện riêng biệt bằng cách sử dụng sapply
theo sau stopifnot
để đảm bảo rằng các giá trị trả về phù hợp với những gì bạn mong đợi, nhưng vapply
dễ dàng hơn một chút (nếu hạn chế hơn, vì mã kiểm tra lỗi tùy chỉnh có thể kiểm tra các giá trị trong giới hạn, v.v. ).
Đây là một ví dụ về vapply
việc đảm bảo kết quả của bạn như mong đợi. Điều này tương đồng với một cái gì đó tôi vừa làm việc trong khi cạo PDF, nơi findD
sẽ sử dụngregexđể khớp với một mẫu trong dữ liệu văn bản thô (ví dụ: tôi muốn có một danh sách split
theo thực thể và một regex để khớp với các địa chỉ trong mỗi thực thể. Đôi khi tệp PDF đã được chuyển đổi không theo thứ tự và sẽ có hai địa chỉ cho một thực thể, đã gây ra sự tồi tệ).
> input1 <- list( letters[1:5], letters[3:12], letters[c(5,2,4,7,1)] )
> input2 <- list( letters[1:5], letters[3:12], letters[c(2,5,4,7,15,4)] )
> findD <- function(x) x[x=="d"]
> sapply(input1, findD )
[1] "d" "d" "d"
> sapply(input2, findD )
[[1]]
[1] "d"
[[2]]
[1] "d"
[[3]]
[1] "d" "d"
> vapply(input1, findD, "" )
[1] "d" "d" "d"
> vapply(input2, findD, "" )
Error in vapply(input2, findD, "") : values must be length 1,
but FUN(X[[3]]) result is length 2
Như tôi nói với các sinh viên của mình, một phần của việc trở thành một lập trình viên là thay đổi suy nghĩ của bạn từ "lỗi là khó chịu" thành "lỗi là bạn của tôi."
Đầu vào độ dài bằng không
Một điểm liên quan là nếu độ dài đầu vào bằng 0, sapply
sẽ luôn trả về một danh sách trống, bất kể kiểu đầu vào là gì. So sánh:
sapply(1:5, identity)
sapply(integer(), identity)
vapply(1:5, identity)
vapply(integer(), identity)
Với vapply
, bạn được đảm bảo có một loại đầu ra cụ thể, vì vậy bạn không cần phải viết thêm kiểm tra cho các đầu vào có độ dài bằng không.
Điểm chuẩn
vapply
có thể nhanh hơn một chút vì nó đã biết định dạng nó sẽ mong đợi kết quả.
input1.long <- rep(input1,10000)
library(microbenchmark)
m <- microbenchmark(
sapply(input1.long, findD ),
vapply(input1.long, findD, "" )
)
library(ggplot2)
library(taRifx)
autoplot(m)