r - 在请求缺少的列表元素时,我可以覆盖 `$` 或 `[[` 以抛出错误而不是 NULL 吗?

标签 r list fail-fast

我的直觉是这是对 R 语言的滥用,并且有充分的理由不会发生这种情况。但我发现这是我尝试调试的代码中潜在错误的永久来源:

MWE

list.1 <- list(a=1,b=2,c=list(d=3))
list.2 <- list(b=4,c=list(d=6,e=7))
input.values <- list(list.1,list.2)
do.something.to.a.list <- function(a.list) {
    a.list$b <- a.list$c$d + a.list$a
    a.list
}
experiment.results <- lapply(input.values,do.something.to.a.list)

use.results.in.some.other.mission.critical.way <- function(result) {
    result <- result^2
    patient.would.survive.operation <- mean(c(-5,result)) >= -5
    if(patient.would.survive.operation) {
        print("Congrats, the patient would survive! Good job developing a safe procedure.")
    } else {
        print("Sorry, the patient won't make it.")
    }
}

lapply(experiment.results, function(x) 

use.results.in.some.other.mission.critical.way(x$b))

YES 我知道这是一个愚蠢的例子,我可以在尝试访问它之前添加一个元素是否存在的检查。但我并不是想知道如果我始终拥有完美的内存力和意识,我可以做什么,慢慢地解决这个功能不方便并且让我很头疼的事实。我正试图完全避免令人头疼的问题,也许是以牺牲代码速度为代价的。

所以:我想知道的是...

(a) 是否可以这样做。我最初的尝试失败了,我在尝试阅读“$”的 C 内部结构以了解如何正确处理参数时遇到了困难

(b) 如果是这样,是否有充分的理由不(或不)这样做。

基本上,我的想法是,与其编写依赖于列表访问的非空返回的每个函数来仔细检查,我可以只编写一个函数来仔细检查并相信其余函数不会在未满足前提条件的情况下被调用 b/c 失败的列表访问将快速失败。

最佳答案

您几乎可以覆盖 R 中的任何内容(某些特殊值除外 - NULLNANA_integer_ NA_real_ NA_complex_, NA_character_, NaN, Inf, TRUE, FALSE 据我所知)。

对于您的具体情况,您可以这样做:

`$` <- function(x, i) {
  if (is.list(x)) {
    i_ <- deparse(substitute(i))
    x_ <- deparse(substitute(x))
    if (i_ %in% names(x)) {
      eval(substitute(base::`$`(x, i)), envir = parent.frame())
    } else {
      stop(sprintf("\"%s\" not found in `%s`", i_, x_))
    }
  } else {
    eval(substitute(base::`$`(x, i)), envir = parent.frame())
  }
}

`[[` <- function(x, i) {
  if (is.list(x) && is.character(i)) {
    x_ <- deparse(substitute(x))
    if (i %in% names(x)) {
      base::`[[`(x, i)
    } else {
      stop(sprintf("\"%s\" not found in `%s`", i, x_))
    }
  } else {
    base::`[[`(x, i)
  }
}

例子:

x <- list(a = 1, b = 2)
x$a
#[1] 1
x$c
#Error in x$c : "c" not found in `x`
col1 <- "b"
col2 <- "d"
x[[col1]]
#[1] 2
x[[col2]]
#Error in x[[col2]] : "d" not found in `x`

它会大大降低你的代码速度:

microbenchmark::microbenchmark(x$a, base::`$`(x, a), times = 1e4)
#Unit: microseconds
#            expr    min     lq     mean median      uq      max neval
#             x$a 77.152 81.398 90.25542 82.814 85.2915 7161.956 10000
# base::`$`(x, a)  9.910 11.326 12.89522 12.033 12.3880 4042.646 10000

我已将其限制为 list(将包括 data.frame)并已通过数字实现了 [[ 的选择和字符向量,但这可能无法完全代表 $[[ 的使用方式。

注意 [[ 你可以使用@rawr 的更简单的代码:

`[[` <- function(x, i) if (is.null(res <- base::`[[`(x, i))) simpleError('NULL') else res

但是对于 NULL 而不仅仅是未定义的列表成员,这将引发错误。例如

x <- list(a = NULL, b = 2)
x[["a"]]

这当然可能是我们想要的。

关于r - 在请求缺少的列表元素时,我可以覆盖 `$` 或 `[[` 以抛出错误而不是 NULL 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31788031/

相关文章:

r - 将变量名称粘贴到 mutate(across()) 内

r - dplyr summarise_each() 对同一组中的不同列子集使用多个函数

java - 即使数据库已关闭,如何使 Spring 服务器启动?

python - 将两个列表与键和值组合成一个字典并转换为数据框

python - 迭代时修改list和dictionary,为什么在dict上会失败?

java - 在将元素添加到集合之前声明迭代器

r - 具有 Lubridate 持续时间的 Data.frame 摘要

r - doParallel "foreach"不一致地从父环境 : "Error in { : task 1 failed - "could not find function. 继承对象..”

JavaScript div 排序脚本错误(切换下面两个 div 的顺序)