是否有R等价的python的字符串`format`函数?

时间:2021-01-22 20:15:08

In python there's a nice function (str .format) that can really easily replace variables (encoded like {variable}) in a string with values stored in a dict (with values named by variable name). Like so:

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

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

Sammy the shark ate a fish.

鲨鱼萨米吃了一条鱼。

What is the simplest solution in R? Is there a built-in equivalent 2-argument function that takes a string with variables encoded in the same way and replaces them with named values from a named list?

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

If there is no built-in function in R, is there one in a published package?

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

If there is none in a published package, what would you use to write one?

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

The rules: the string is given to you with variables encoded like "{variable}". The variables must be encoded as a list. I will answer with my custom-made version, but will accept an answer that does it better than I did.

规则:字符串由编码为“{variable}”的变量提供给您。必须将变量编码为列表。我会回答我的定制版本,但会接受一个比我更好的答案。

5 个解决方案

#1


8  

I found another solution: glue package from the tidyverse: https://github.com/tidyverse/glue

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

An example:

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

If you insist on having list of variables, you can do:

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

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

Regards

Paweł

#2


3  

Here's a function that converts the { and } to <%= and %> and then uses brew from the brew package (which you need to install):

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

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

Tests:

> 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.

It will fail if there's any { in the format string that don't mark variable substitutions, or if it has <%= or any of the other brew syntax markers in it.

如果格式字符串中的任何{未标记变量替换,或者其中包含<%=或任何其他brew语法标记,则它将失败。

#3


2  

Since it appears I cannot find a built-in or even a package with such a function, I tried to roll my own. My function relies on the stringi package. Here is what I have come up with:

因为看起来我找不到内置的甚至是具有这种功能的包,所以我试着自己滚动。我的函数依赖于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)
}

Example:

> 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."

#4


2  

The stringr package almost has an exact replacement in the function str_interp. it requires just a bit of adjustment:

stringr包几乎在函数str_interp中有一个确切的替换。它只需要一点调整:

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

#5


0  

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.

#1


8  

I found another solution: glue package from the tidyverse: https://github.com/tidyverse/glue

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

An example:

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

If you insist on having list of variables, you can do:

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

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

Regards

Paweł

#2


3  

Here's a function that converts the { and } to <%= and %> and then uses brew from the brew package (which you need to install):

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

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

Tests:

> 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.

It will fail if there's any { in the format string that don't mark variable substitutions, or if it has <%= or any of the other brew syntax markers in it.

如果格式字符串中的任何{未标记变量替换,或者其中包含<%=或任何其他brew语法标记,则它将失败。

#3


2  

Since it appears I cannot find a built-in or even a package with such a function, I tried to roll my own. My function relies on the stringi package. Here is what I have come up with:

因为看起来我找不到内置的甚至是具有这种功能的包,所以我试着自己滚动。我的函数依赖于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)
}

Example:

> 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."

#4


2  

The stringr package almost has an exact replacement in the function str_interp. it requires just a bit of adjustment:

stringr包几乎在函数str_interp中有一个确切的替换。它只需要一点调整:

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

#5


0  

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.