Để trả lời điều này không phải từ quan điểm thẩm mỹ nhưng định hướng hiệu suất, tôi đã đưa tất cả các đề xuất trên thông qua một điểm chuẩn . Nói chính xác, tôi đã xem xét các đề xuất
x[length(x)]
mylast(x)
, mylast
chức năng C ++ được triển khai ở đâu thông qua Rcpp,
tail(x, n=1)
dplyr::last(x)
x[end(x)[1]]]
rev(x)[1]
và áp dụng chúng cho các vectơ ngẫu nhiên có kích thước khác nhau (10 ^ 3, 10 ^ 4, 10 ^ 5, 10 ^ 6 và 10 ^ 7). Trước khi chúng tôi xem xét các con số, tôi nghĩ rằng rõ ràng rằng bất cứ điều gì trở nên chậm hơn đáng kể với kích thước đầu vào lớn hơn (nghĩa là, bất cứ điều gì không phải là O (1)) không phải là một lựa chọn. Đây là mã mà tôi đã sử dụng:
Rcpp::cppFunction('double mylast(NumericVector x) { int n = x.size(); return x[n-1]; }')
options(width=100)
for (n in c(1e3,1e4,1e5,1e6,1e7)) {
x <- runif(n);
print(microbenchmark::microbenchmark(x[length(x)],
mylast(x),
tail(x, n=1),
dplyr::last(x),
x[end(x)[1]],
rev(x)[1]))}
Nó đưa cho tôi
Unit: nanoseconds
expr min lq mean median uq max neval
x[length(x)] 171 291.5 388.91 337.5 390.0 3233 100
mylast(x) 1291 1832.0 2329.11 2063.0 2276.0 19053 100
tail(x, n = 1) 7718 9589.5 11236.27 10683.0 12149.0 32711 100
dplyr::last(x) 16341 19049.5 22080.23 21673.0 23485.5 70047 100
x[end(x)[1]] 7688 10434.0 13288.05 11889.5 13166.5 78536 100
rev(x)[1] 7829 8951.5 10995.59 9883.0 10890.0 45763 100
Unit: nanoseconds
expr min lq mean median uq max neval
x[length(x)] 204 323.0 475.76 386.5 459.5 6029 100
mylast(x) 1469 2102.5 2708.50 2462.0 2995.0 9723 100
tail(x, n = 1) 7671 9504.5 12470.82 10986.5 12748.0 62320 100
dplyr::last(x) 15703 19933.5 26352.66 22469.5 25356.5 126314 100
x[end(x)[1]] 13766 18800.5 27137.17 21677.5 26207.5 95982 100
rev(x)[1] 52785 58624.0 78640.93 60213.0 72778.0 851113 100
Unit: nanoseconds
expr min lq mean median uq max neval
x[length(x)] 214 346.0 583.40 529.5 720.0 1512 100
mylast(x) 1393 2126.0 4872.60 4905.5 7338.0 9806 100
tail(x, n = 1) 8343 10384.0 19558.05 18121.0 25417.0 69608 100
dplyr::last(x) 16065 22960.0 36671.13 37212.0 48071.5 75946 100
x[end(x)[1]] 360176 404965.5 432528.84 424798.0 450996.0 710501 100
rev(x)[1] 1060547 1140149.0 1189297.38 1180997.5 1225849.0 1383479 100
Unit: nanoseconds
expr min lq mean median uq max neval
x[length(x)] 327 584.0 1150.75 996.5 1652.5 3974 100
mylast(x) 2060 3128.5 7541.51 8899.0 9958.0 16175 100
tail(x, n = 1) 10484 16936.0 30250.11 34030.0 39355.0 52689 100
dplyr::last(x) 19133 47444.5 55280.09 61205.5 66312.5 105851 100
x[end(x)[1]] 1110956 2298408.0 3670360.45 2334753.0 4475915.0 19235341 100
rev(x)[1] 6536063 7969103.0 11004418.46 9973664.5 12340089.5 28447454 100
Unit: nanoseconds
expr min lq mean median uq max neval
x[length(x)] 327 722.0 1644.16 1133.5 2055.5 13724 100
mylast(x) 1962 3727.5 9578.21 9951.5 12887.5 41773 100
tail(x, n = 1) 9829 21038.0 36623.67 43710.0 48883.0 66289 100
dplyr::last(x) 21832 35269.0 60523.40 63726.0 75539.5 200064 100
x[end(x)[1]] 21008128 23004594.5 37356132.43 30006737.0 47839917.0 105430564 100
rev(x)[1] 74317382 92985054.0 108618154.55 102328667.5 112443834.0 187925942 100
Điều này ngay lập tức loại trừ bất cứ điều gì liên quan rev
hoặc end
vì chúng rõ ràng là không O(1)
(và các biểu thức kết quả được đánh giá theo kiểu không lười biếng). tail
và dplyr::last
không xa O(1)
nhưng họ cũng chậm hơn đáng kể so với mylast(x)
và x[length(x)]
. Vì mylast(x)
chậm hơn x[length(x)]
và không cung cấp lợi ích (thay vào đó, nó tùy chỉnh và không xử lý một vectơ trống một cách duyên dáng), tôi nghĩ rằng câu trả lời là rõ ràng: Vui lòng sử dụngx[length(x)]
.