是否有 R 等效于 python 的字符串“格式”函数?

Posted

技术标签:

【中文标题】是否有 R 等效于 python 的字符串“格式”函数?【英文标题】:Is there an R equivalent of python's string `format` function? 【发布时间】: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") 【参考方案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.

【讨论】:

以上是关于是否有 R 等效于 python 的字符串“格式”函数?的主要内容,如果未能解决你的问题,请参考以下文章

是否有 Python 等效于正则表达式的 Perl "/x" 修饰符?

R 等效于 python 的 os.getpid() 用于并行处理

R 中是不是有类似于 Python 的 % 的字符串格式化运算符?

等效于 Visual C++ 中 gcc 的 __attribute__ 格式

Matlab .Fig 等效于 R

R中是不是有等效于“count if”函数的功能?