【问题标题】:Is there an R equivalent of python's string `format` function?是否有 R 等效于 python 的字符串“格式”函数?
【发布时间】:2017-11-29 11:46:33
【问题描述】:

在 python 中有一个很好的函数 (str .format) 可以很容易地将字符串中的变量(编码为 {variable})替换为存储在 dict 中的值(使用变量名命名的值)。像这样:

vars=dict(animal="shark", verb="ate", noun="fish")
string="Sammy the {animal} {verb} a {noun}."
print(string.format(**vars)) 

鲨鱼萨米吃了一条鱼。

R 中最简单的解决方案是什么?是否有一个内置的等效 2 参数函数,它接受一个字符串,其中变量编码 相同 方式并将它们替换为来自命名list的命名值?

如果 R 中没有内置函数,那么发布的包中是否有内置函数?

如果已发布的包中没有,你会用什么来编写?

规则:字符串是用编码为“{variable}”的变量提供给您的。变量必须编码为list。我会用我的定制版本来回答,但会接受比我做得更好的答案。

【问题讨论】:

  • 我会非常自信地伸出脖子说“不”。未内置在基础 R 中。附加包中可能存在与此完全相同的内容。有 类似 的东西可以进行变量替换(例如 brew 包),但您希望使用这种 {name} 语法精确编码的格式,是吗?
  • 是的;该字符串已经为以 python 为中心的分析而构建,因此我无法更改变量的编码方式。
  • brew 使用 <%=%> 作为标记。如果您不希望字符串中出现<%= 或在任何地方转义了{},则用它们替换{} 会起作用。
  • 我不知道 R 中格式函数的任何等效项,但是您有一个 printf C 函数的等效项,它允许您放置要打印的内容和变量列表。见rdocumentation.org/packages/R.utils/versions/2.5.0/topics/…
  • sprintf() 是核心包中最接近的。它不使用命名替换组,但可以做索引组​​:sprintf("%1$s %1$s %2$s %3$s", "a", "b", "c")

标签: r replace


【解决方案1】:

由于我找不到具有这种功能的内置甚至包,因此我尝试自行开发。我的功能依赖于stringi 包。这是我想出的:

strformat = function(str, vals) {
    vars = stringi::stri_match_all(str, regex = "\\{.*?\\}", vectorize_all = FALSE)[[1]][,1]
    x = str
    for (i in seq_along(names(vals))) {
        varName = names(vals)[i]
        varCode = paste0("{", varName, "}")
        x = stringi::stri_replace_all_fixed(x, varCode, vals[[varName]], vectorize_all = TRUE)
    }
    return(x)
}

例子:

> str = "Sammy the {animal} {verb} a {noun}."
> vals = list(animal="shark", verb="ate", noun="fish")

> strformat(str, vals)
[1] "Sammy the shark ate a fish."

【讨论】:

    【解决方案2】:

    这是一个将{} 转换为<%=%> 的函数,然后使用brew 包(您需要安装)中的brew

    form = function(s,...){
     s = gsub("\\}", "%>", gsub("\\{","<%=",s))
     e = as.environment(list(...))
     parent.env(e)=.GlobalEnv
     brew(text=s, envir=e)
    }
    

    测试:

    > form("Sammy the {animal} {verb} a {noun}.", animal = "shark", verb="made", noun="car")
    Sammy the shark made a car.
    > form("Sammy the {animal} {verb} a {noun}.", animal = "shark", verb="made", noun="truck")
    Sammy the shark made a truck.
    

    如果格式字符串中有任何{ 没有标记变量替换,或者它有&lt;%= 或任何其他brew 语法标记,它将失败。

    【讨论】:

    • 这比我的版本更简洁——但我认为如果它接受变量的list 会更有用
    • 在这种情况下尝试form = function(s,L){e = as.environment(L)(未经测试)。我的基础是 python 的字符串格式方法,它实际上并不需要一个字典,而是一个参数列表(你可以用星号转换它,就像 OP 现在在编辑中所做的那样!
    【解决方案3】:

    我找到了另一个解决方案:来自 tidyverse 的胶水包: https://github.com/tidyverse/glue

    一个例子:

    library(glue)
    animal <- "shark"
    verb <- "ate"
    noun <- "fish"
    string="Sammy the {animal} {verb} a {noun}."
    glue(string)
    Sammy the shark ate a fish.
    

    如果你坚持有变量列表,你可以这样做:

    l <- list(animal = "shark", verb = "ate", noun = "fish")
    do.call(glue, c(string , l))
    Sammy the shark ate a fish.
    

    问候

    帕维尔

    【讨论】:

    • 最好使用with:with(l, glue(string))
    【解决方案4】:

    stringr几乎在函数 str_interp 中有一个完全替换。它只需要一点调整:

    fmt = function(str, vals) {
        # str_interp requires variables encoded like ${var}, so we substitute
        # the {var} syntax here.
        str = stringr::str_replace_all(str, "\\{", "${")
        stringr::str_interp(str, vals)
    }
    

    【讨论】:

    • 错误示例...传入“str”和“vals”,引用“x”和“args”。
    • 修复了 args 以便它们匹配
    【解决方案5】:
    library(glue)
    
    list2env(list(animal="shark", verb="ate", noun="fish"),.GlobalEnv)
    string="Sammy the {animal} {verb} a {noun}."
    glue(string)
    
    Sammy the shark ate a fish.
    

    【讨论】:

      猜你喜欢
      • 2021-12-17
      • 2012-01-22
      • 2019-09-17
      • 1970-01-01
      • 2015-05-10
      • 1970-01-01
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多