强制将空白变量名称转换为开关

时间:2017-10-05 13:15:03

标签: r function switch-statement

我写了这个小实用程序函数来很好地格式化货币值:

代码

#' @title Money Format
#'
#' @description
#' The \code{money_format} function takes a numeric vector and returns formatted currency with pound sign.
#'
#' @param x numeric vector to be converted to currency
#' @param include_pound_sign A logical, defulats to \code{TRUE}.
#' @param digits An integer. Number of digits to pass to format.
#'
#' @details
#' The \code{money_format} function can be also used to pass nice UK-style SI unit formats
#'   with \code{include_pound_sign = FALSE}.
#'
#' @return
#' A character vector with suffiexes and pund sign
#'
#' @import scales
#'
#' @export
#'
#' @examples
#' money_format(1e6)
money_format <- function(x, include_pound_sign = TRUE, digits = 3) {
    stopifnot(is.numeric(x))

    # As per: https://stackoverflow.com/a/28160474/1655567
    f <-
        function(x) {
            div <- findInterval(x, c(1, 1e3, 1e6, 1e9, 1e12))
            suffixes <- c("_", "K", "m", "bn", "T")

            paste0({
                if (include_pound_sign) {
                    intToUtf8(163)
                }
            }
            , (
                scales::unit_format(
                    unit = suffixes[div],
                    scale = switch(
                        suffixes[div],
                        "_" = 1,
                        K = 1e-3,
                        m = 1e-6,
                        bn = 1e-9,
                        "T" =  1e-12
                    ),
                    sep = "",
                    digits = digits
                )
            )(x))
        }

    vf <- Vectorize(FUN = f, "x")

    vf(x)
}

实施例

>> money_format(1e3)
[1] "£1K"
>> money_format(1e6)
[1] "£1m"

问题

我想将100显示为£100。问题是我使用switch来选择后缀,我不能在那里使用""作为变量名。到目前为止,我能够强制 "_" 作为变量名称,这样可以:

>> money_format(10)
[1] "£10_"

但我不想那样,我想要£10。问题是我不能拥有:

   scale = switch(
                  suffixes[div],
                  "" = 1,
                # ^ - this fails

期望的解决方案

我不想重写此功能,我可以使用一些技巧在"" = 1语句中打印出switch的空格吗?

2 个答案:

答案 0 :(得分:1)

这将为1使用默认值switch,并允许suffixes为零长度字符串

money_format <- function(x, include_pound_sign = TRUE, digits = 3) {
  stopifnot(is.numeric(x))
  div <- findInterval(x, c(1, 1e3, 1e6, 1e9, 1e12))
  suffixes <- c("", "K", "m", "bn", "T")
  sapply(seq_along(div), function(y) {
    sprintf("%s%s",
            ifelse(include_pound_sign, intToUtf8(163), NULL),
            scales::unit_format(
              unit = suffixes[div][y],
              scale = switch(
                suffixes[div][y],
                K = 1e-3,
                m = 1e-6,
                bn = 1e-9,
                "T" =  1e-12,
                1),
              sep = "",
              digits = digits
            )(x[y]))
    })
  }

val <- c(1.235e3, 1e6, 1009, 10)
money_format(val)
[1] "£1.24K" "£1m"    "£1.01K" "£10"  

答案 1 :(得分:0)

这样的事情:

money_format <- function(x, include_pound_sign = TRUE, digits = 3) {
  stopifnot(is.numeric(x))

  # As per: https://stackoverflow.com/a/28160474/1655567
  f <-
    function(x) {
      div <- findInterval(x, c(1, 1e3, 1e6, 1e9, 1e12))
      suffixes <- c("_", "K", "m", "bn", "T")

      scale = switch(
        suffixes[div],
        "_" = 1,
        K = 1e-3,
        m = 1e-6,
        bn = 1e-9,
        "T" =  1e-12
      )

      if(scale == 1){
        suffixes[1] = ""
      }

      paste0({
        if (include_pound_sign) {
          intToUtf8(163)
        }
      }
      , (
        scales::unit_format(
          unit = suffixes[div],
          scale = scale,
          sep = "",
          digits = digits
        )
      )(x))
    }

  vf <- Vectorize(FUN = f, "x")

  vf(x)
}

我基本上在switch之前完成paste0,并在"_"之后用""替换switch,因为不再需要suffixes

<强>结果:

> money_format(10)
[1] "£10"
> money_format(100)
[1] "£100"
> money_format(1000)
[1] "£1K"
> money_format(10000)
[1] "£10K"
> money_format(100000)
[1] "£100K"