【问题标题】:Which is faster for list-element extraction, [[ or $?列表元素提取哪个更快,[[ 或 $?
【发布时间】:2014-07-29 08:29:25
【问题描述】:

所以,我注意到this question 提到了一个人的经验,[[$ 更快地提取列表元素,但是我想知道是否有人从 R 版本 >= 3.0.2 起有明确的答案?

我的一位同事已经看到$ 更快的情况,但这是前一段时间(以及使用 Rcpp),我想知道 R 的演变是否发生了任何变化......

【问题讨论】:

标签: r performance list subset


【解决方案1】:

只需针对您的案例运行一些基准测试。像这样的:

mylist <- replicate(1e2, list(rnorm(1e3), sample(LETTERS, 1e2, TRUE)))
names(mylist) <- paste("X", seq_along(mylist))

library(rbenchmark)
benchmark(for (i in seq_len(1e4)) mylist$X1,
          for (i in seq_len(1e4)) mylist$"X1",
          for (i in seq_len(1e4)) mylist[["X1"]],
          for (i in seq_len(1e4)) mylist[["X1", exact = FALSE]],
          for (i in seq_len(1e4)) mylist[[1]],
          for (i in seq_len(1e4)) mylist$X50,
          for (i in seq_len(1e4)) mylist$"X50",
          for (i in seq_len(1e4)) mylist[["X50"]],
          for (i in seq_len(1e4)) mylist[["X50", exact = FALSE]],
          for (i in seq_len(1e4)) mylist[[50]],
          for (i in seq_len(1e4)) mylist$X100,
          for (i in seq_len(1e4)) mylist$"X100",
          for (i in seq_len(1e4)) mylist[["X100"]],
          for (i in seq_len(1e4)) mylist[["X100", exact = FALSE]],
          for (i in seq_len(1e4)) mylist[[100]],
          replications=100,
          columns=c('test', 'elapsed', 'replications', 'relative'),
          order='relative')

#                                                        test elapsed replications relative
#5                      for (i in seq_len(10000)) mylist[[1]]    0.20          100     1.00
#10                    for (i in seq_len(10000)) mylist[[50]]    0.22          100     1.10
#15                   for (i in seq_len(10000)) mylist[[100]]    0.22          100     1.10
#8                  for (i in seq_len(10000)) mylist[["X50"]]    2.76          100    13.80
#3                   for (i in seq_len(10000)) mylist[["X1"]]    2.87          100    14.35
#13                for (i in seq_len(10000)) mylist[["X100"]]    2.87          100    14.35
#6                       for (i in seq_len(10000)) mylist$X50    4.48          100    22.40
#7                       for (i in seq_len(10000)) mylist$X50    4.49          100    22.45
#12                     for (i in seq_len(10000)) mylist$X100    4.63          100    23.15
#1                        for (i in seq_len(10000)) mylist$X1    4.64          100    23.20
#2                        for (i in seq_len(10000)) mylist$X1    4.66          100    23.30
#11                     for (i in seq_len(10000)) mylist$X100    4.67          100    23.35
#9   for (i in seq_len(10000)) mylist[["X50", exact = FALSE]]    5.56          100    27.80
#4    for (i in seq_len(10000)) mylist[["X1", exact = FALSE]]    5.62          100    28.10
#14 for (i in seq_len(10000)) mylist[["X100", exact = FALSE]]    5.76          100    28.80

R.version
#platform       x86_64-w64-mingw32          
#arch           x86_64                      
#os             mingw32                     
#system         x86_64, mingw32             
#status                                     
#major          3                           
#minor          1.1                         
#year           2014                        
#month          07                          
#day            10                          
#svn rev        66115                       
#language       R                           
#version.string R version 3.1.1 (2014-07-10)
#nickname       Sock it to Me 

【讨论】:

  • [[exact=FALSE]] 怎么样?
  • 这是最慢的变种。
  • 是的,这个想法是为了展示比较,以及它如何获取类似于$ 的值。 +1。
【解决方案2】:

我认为链接的问答确实应该回答这个问题,但正如我猜想的任何答案一样,这取决于。我认为重要的是[[设计 尽可能快,给定默认值,exact=TRUE 因此应该是 goto 方法,除非你有特定的理由不这样做(其他人可能不同意)。这是源代码中的 cmets。以下内容来自/src/main/subset.c。行号供参考:

[ 子集:

  #635 /* The "[" subset operator.
  #636  * This provides the most general form of subsetting. */
  #637 
  #638 SEXP attribute_hidden do_subset(SEXP call, SEXP op, SEXP args, SEXP rho)
  #639 { ... }

[[ 子集:

  #865 /* The [[ subset operator.  It needs to be fast. */
  #866 /* The arguments to this call are evaluated on entry. */
  #867 
  #868 SEXP attribute_hidden do_subset2(SEXP call, SEXP op, SEXP args, SEXP rho)
  #869 { ... }

$ 子集:

 #1105 /* The $ subset operator.
 #1106    We need to be sure to only evaluate the first argument.
 #1107    The second will be a symbol that needs to be matched, not evaluated.
 #1108 */
 #1109 SEXP attribute_hidden do_subset3(SEXP call, SEXP op, SEXP args, SEXP env)
 #1110 { ... }

【讨论】:

    猜你喜欢
    • 2021-09-15
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多