多重ループを一重ループに変えるための範囲リスト作成

コメント等はこちらのページにどうぞ -> 多重ループを一重ループに変えるための範囲リスト作成へのコメント

解説

  • mult.range 関数は多重ループを見かけ上一重ループに変えるための、範囲リストを作る関数
  • R の for ループには範囲として任意のリストが許されることを使っている

注意

  • 見かけ上一重ループに変えるだけで本質的には多重ループであることに変わり無い
  • 最大の長所はコードが簡潔になることにある
  • 多重範囲リストを作るための時間とメモリ量と言うオバーヘッドがある
  • 同じ多重範囲ループが何度も出てくる場合は多少早くなる(こともある)
  • 文字列、実数が交じると少し問題が生じる(以下の例を参照)

TODO

  • 範囲引数を一度に任意個数与えるようにするにはどうしたら良いのか?
  • 多重範囲リストをもっと効率的に作る裏技?
  • 引数妥当性のチェック(そこまでする必要は無いか?)
mult.range <- function(x, y) {    # x, y はループ範囲を与えるベクトル
 mr <- as.list(NA)                      # 空リスト
 ct <- 0                                     # 添字カウンタ
 for (i in x) for (j in y) mr[[ct <- ct +1]] <- c(i, j)
 return(mr)
}

使用例

> Range <- mult.range(1:10, 1:5)
> for (i in 1:10) for (j in 1:5) i+j   # 二重ループ
> for (x in Range) x[1] + x[2]     # 上の一重ループ化。x[1], x[2] がループ変数の役目  
> Range[[1]]        # 1 番目の成分
[1] 1 1
> Range <- mult.range(mult.range(1:10, 1:5), 1:20)
> for (i in 1:10) for (j in 1:5) for(k in 1:20) foo(i, j, k)   # 3重ループ
> for (x in Range) foo(x[1],  x[2],  x[3])                       # 上の一重ループ化 (コードが簡潔!)
> Range <- mult.range(1:10, runif(5))   # ループ範囲は実数ベクトルでも良い
> m <- 0 
> for (x in Range)  m <- m + x[1]*x[2]  
>  m
[1] 73.22538
> length(Range)    # 多重ループ範囲リストの成分数
[1] 50
> x <- Range[[12]]        # 12 番目の成分
> x 
[1] 3.0000000 0.6013451   # 実数化されている!
> (1:10)[x[1]]                      # しかし、そのまま配列の添字等に使ってOK(自動的に整数に強制変換されるらしい?)
[1] 3
> Range <- mult.range(1:3, c("A", "B", "C"))  # ループ範囲が文字ベクトル
> Range[[10]]
[1] "4" "A"               # まずい、数字が文字化されている(ベクトルに数字と文字は一緒に入れられない)
> for (x in Range) cat(x[2], " is ", as.integer(x[1]), "\n")   # しょうがないから整数化  
A  is  1
B  is  1
C  is  1
(以下略)

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Google
WWW を検索 OKADAJP.ORG を検索
Last-modified: 2015-03-01 (日) 01:15:59 (1720d)