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]

forRのループでこの不要な逆反復を簡単に防ぐ方法は?

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")
+ }

リストに項目が 1 つしかない場合、サブリストは空になり、for ループはスキップされます。

編集: GavinSimpson が指摘しているように、特定のケースではインデックスをループする必要がなかったので、これはうまく機能します。インデックスが絶対に必要な場合は、Andrie が示したseq_along(x[-1])のではなく、ループする必要があります。x[-1]

于 2012-10-19T11:11:17.910 に答える
2

正しい答えは、関数に対して入力検証を行うことだと思います。この動作を「回避」するスパゲッティ コードを作成するのではなく、入力変数の長さをテストするかtypeof、各要素をチェックするなどして ください。

あなたの例では、単純なもの if (length(x)<2) #skip the loop section of codeで十分です。

于 2012-10-19T11:14:03.703 に答える