3

考虑下面的代码:

foo = list("First List", 1, 2, 3)
bar = function(x) {
    cat("The list name is:", x[[1]], "\nThe items are:\n")
    for (i in 2:length(x))
        cat(x[[i]], "\n")
}
bar(foo)

结果将是:

The list name is: First List 
The items are:
1 
2 
3 

现在考虑传递一个没有项目但有名称的列表:

baz = list("Second List")
bar(baz)

结果将是:

The list name is: Second List 
The items are:
Error in x[[i]] : subscript out of bounds

错误是因为2:length(x)c(2, 1)为后一种情况产生一个序列bar(baz),所以它尝试访问baz[2]并且它不存在。

如何for在 R 的循环中简单地防止这种不需要的反向迭代?

4

3 回答 3

9

seq_along有助于:

bar <- function(x) {
  cat("The list name is:", x[[1]], "\nThe items are:\n")
  for (i in seq_along(x[-1])) cat(x[[i+1]], "\n")   ### Edit ###
}

结果:

bar(foo)
The list name is: First List 
The items are:
First List 
1 
2 
3 

bar(baz)
The list name is: Second List 
The items are:
Second List 

当然,最好不要使用for循环,而是lapply或家庭:

bar <- function(x) {
  cat("The list name is:", x[[1]], "\nThe items are:\n")
  lapply(x[-1],  function(xx)cat(xx, "\n"))
  invisible(NULL)
}

bar(foo)
The list name is: First List 
The items are:
1 
2 
3 

bar(baz)
The list name is: Second List 
The items are:
于 2012-10-19T11:10:15.463 回答
4

无需遍历列表索引,您只需遍历子列表即可:

> bar = function(x) {
+     cat("The list name is:", x[[1]], "\nThe items are:\n")
+     for (i in x[-1])
+         cat(i, "\n")
+ }

如果列表中有单个项目,则子列表将为空,并且将跳过 for 循环。

编辑:正如 GavinSimpson 指出的那样,这很有效,因为您的特定情况并不需要遍历索引。如果绝对需要索引,那么您将不得不循环seq_along(x[-1])而不是x[-1]像 Andrie 显示的那样。

于 2012-10-19T11:11:17.910 回答
2

我认为正确的答案是:对您的函数进行输入验证。而不是创建意大利面条代码来“解决”这种行为,而是测试您的输入变量的长度,或检查typeof每个元素等。

在您的示例中,一个简单的 if (length(x)<2) #skip the loop section of code就足够了。

于 2012-10-19T11:14:03.703 回答