代码之家  ›  专栏  ›  技术社区  ›  landau

用多个值替换表达式中的一个符号

  •  2
  • landau  · 技术社区  · 6 年前

    给定一个任意的固定表达式,我想用多个值的集合替换一个符号。实例:

    Expression       | Symbol | Replace with               | Desired Output
    -----------------------------------------------------------------------------------------
    f(x, 5)          | x      | a = 1, b = sym, c = "char" | f(a = 1, b = sym, c = "char", 5)
    g(f(h(y)), z)    | y      | 1, 2, 3                    | g(f(h(1, 2, 3)), z)
    g(f(h(y), z), z) | z      | 4, x                       | g(f(h(y), 4, x), 4, x)
    

    这个 substitute() 函数很接近,但它不是我想要的。在下面的示例中,我希望 f(x) 进入之内 f(1, b = 4, c = d) 但是我还没有找到合适的 env 争论。

    substitute(
      expr = f(x),
      env = list(x = list(1, b = 4, c = rlang::sym("d")))
    )
    #> f(list(1, b = 4, c = d))
    
    substitute(
      expr = f(x),
      env = list(x = as.call(c(quote(x), 1, b = 4, c = quote(d)))[-1])
    )
    #> f(1(b = 4, c = d))
    

    创建日期:2019-02-09 reprex package (v0.2.1)

    有没有可能找到 埃恩 这样 substitute(f(x), env) 等于 F(1,B=4,C=D) ?

    评论:

    2 回复  |  直到 6 年前
        1
  •  1
  •   MrFlick    6 年前

    这是一个拼接函数

    splice <- function(x, replacements) {
      if (is(x, "call")) {
        as.call(do.call("c",lapply(as.list(x), splice, replacements), quote=T))
      } else if (is(x, "name")) {
        if (deparse(x) %in% names(replacements)) {
          return(replacements[[deparse(x)]])
        } else {
          list(x)
        }
      } else {
        list(x)
      }
    }
    

    它似乎与样本输入一起工作

    splice(quote(f(x, 5) ), list(x=list(a = 1, b = quote(sym), c = "char" )))
    # f(a = 1, b = sym, c = "char", 5)
    splice(quote(g(f(h(y)), z)) , list(y=list(1,2,3)))
    # g(f(h(1, 2, 3)), z)
    splice(quote(g(f(h(y), z), z)), list(z=list(4, quote(x))) )
    # g(f(h(y), 4, x), 4, x)
    

    基本上你只需要换掉符号名。它还应该使用不在列表中的单个变量替换。

    splice(quote(f(x,5)), list(x=7))
    # f(7, 5)
    

    您基本上需要通过将调用作为列表进行操作来重新编写它。这就是tidyverse函数在幕后所做的。他们截获当前调用,重新编写它,然后评估新扩展的调用。 substitute 不会工作,因为您不只是用一个值替换一个符号。您需要更改传递给函数的参数数目。

        2
  •  0
  •   duckmayr    6 年前

    这个答案很难理解,但(我想)它能满足你的需要;它是受到启发的(一句话取自) this Stack Overflow answer 到一个有点相关的职位:

    multi_substitute <- function(expr, key, ...) {
        expr <- deparse(substitute(expr))
        key <- deparse(substitute(key))
        # The following line is the bit I got from the mentioned SO answer
        l <- sapply( substitute(list(...)), deparse)[-1] 
        l <- paste(names(l), l, sep = " = ")
        l <- sub("^ = ", "", l)
        l <- paste(l, collapse = ",")
        vals <- deparse(substitute(...))
        result <- sub(key, l, expr)
        return(parse(text = result)[[1]])
    }
    multi_substitute(f(x), x, 1, b = 4, c = quote(d))
    # f(1, b = 4, c = quote(d))
    

    你也许能让它更优雅一点,或者量身定做以更好地满足你的需求。

    如果您不想强制提供 key 在这里争论,你当然可以很容易地改变这一点。