胶水零填充

时间:2020-09-03 20:18:54

标签: r r-glue

我想用glue完成sprintf('%02d', x),但我不确定是否有可能。

vignette('transformers')建议使用类似sprintf的转换器sprintf_transformer和“前端”包装器glue_fmt,如下所示:

sprintf_transformer <- function(text, envir) {
  m <- regexpr(":.+$", text)
  if (m != -1) {
    format <- substring(regmatches(text, m), 2)
    regmatches(text, m) <- ""
    res <- eval(parse(text = text, keep.source = FALSE), envir)
    do.call(sprintf, list(glue("%{format}f"), res))
  } else {
    eval(parse(text = text, keep.source = FALSE), envir)
  }
}

glue_fmt <- function(..., .envir = parent.frame()) {
  glue(..., .transformer = sprintf_transformer, .envir = .envir)
}

然后举一个简单的例子:

glue_fmt("π = {pi:.2}")
#> π = 3.14

这似乎依赖于惰性计算,将调用pi:.2(有效的R语法)拆分为对sprintfsprintf('%.2f', pi)的调用。

但是在我看来,这对于0填充而言是不可能的,因为R解析器将消除任何前导0:

pid = as.integer(pi)
glue_fmt('{pid:02}')
# 3.000000
# vs desired
sprintf('%02d', pid)
# [1] "03"

sprintf_transformerf是硬编码的,因为02d.2f本身都不是有效的R语法。我猜我们可以制作glue_fmtdglue_fmtf或添加一个自变量来提供'd''f',但是与普通的glue_fmt

这仍然不会克服R解析器的基本约束-将sprintf视为R代码后,解析器将删除前导0。

因此,我陷入了困境–是否可以使用02进行零填充格式,而不会过于复杂?

1 个答案:

答案 0 :(得分:1)

我认为您不需要在Transfomer中使用有效的R语法。该字符串被作为字符串处理。您无需对f或d进行修正。例如,如果您有

sprintf_transformer <- function(text, envir) {
  m <- regexpr(":.+$", text)
  if (m != -1) {
    format <- substring(regmatches(text, m), 2)
    regmatches(text, m) <- ""
    res <- eval(parse(text = text, keep.source = FALSE), envir)
    do.call(sprintf, list(glue("%{format}"), res))
  } else {
    eval(parse(text = text, keep.source = FALSE), envir)
  }
}

那你就可以做

glue_fmt('{pid:02d}')
# 03
glue_fmt('{pid:0.02f}')
# 3.00