Dangerous for loop idiom?
taking an example from An Introduction to R
xc <- split(x, ind)
yc <- split(y, ind)
for (i in 1:length(yc)) {
plot(xc[[i]], yc[[i]])
abline(lsfit(xc[[i]], y开发者_如何学运维c[[i]]))
}
It seems that for(i in 1:length(yc)) { ...
is an idiom for iterating over a list or vector in the case where you need a handle on the current index. This however breaks in the case of an empty list since 1:0
is not an empty vector. What is the idiom I should use for iterating over list/vector indices when you aren't guaranteed a non-empty list? I'm thinking if(length(yc)) for(i in 1:length(yc)) { ...
but is there a nicer way?
You're looking for seq_along
.
> seq_along(as.list(1:2))
[1] 1 2
> seq_along(list())
integer(0)
You can use seq_along
:
for(i in seq_along(yc)) {...}
I'm pretty sure this bypasses the problem and should be a tiny bit faster.
This question is covered on page 75 of 'The R Inferno': http://www.burns-stat.com/pages/Tutor/R_inferno.pdf
It tells you a few other ways to get your loop wrong as well.
For anyone who happens to stumble upon this -- if you want an index vector based on possibly zero length, rather than another vector, you can safely use seq(1, length.out = L)
, where L can be any non-negative integer. That will give you integer(0)
if L == 0
, and 1:L
otherwise.
Of course the other solutions given here are more concise if L == length(something)
, but I had a problem where that wasn't the case, so I thought I'd write it down for progeny.
Also seq(1, length.out = L)
can be abbreviated as seq_len(L)
, which according to ?seq
is faster.
精彩评论