这是 Tyler 的又一个问题,只是为了复杂化而显得复杂:)
所以你去:
R> x <- c("20(0.23)", "15(0.2)", "16(0.09)")
R> sapply(strsplit(gsub("^(\\d+)\\((.*)\\)$", "\\1 \\2", x), " "),
+ function(x) sprintf("%2d(.%02d)",
+ as.numeric(x[1]),
+ as.numeric(x[2])*100))
[1] "20(.23)" "15(.20)" "16(.09)"
R>
我们在这里做了几件事:
gsub()
挑选两个数字:第一个是括号前的数字,然后是括号内的一个。[事后看来,应该选择小数点后,见下文。]
- 这仅使用空格将它们打印出来,例如
"20 0.23"
第一个。
- 然后,我们对此使用标准
strsplit()
。
- 然后我们
sapply
用来处理我们从中得到的列表strsplit
- 我们将第一个数字打印为两位整数。
- 第二个更棘手 - 该
(s)printf()
系列无法抑制前导零,因此我们打印小数,并打印整数的两位数 - 并相应地转换第二个数字。
这一切都很简洁,在一条线上,但它会更清楚地分解。
编辑:我不经常提供最快的解决方案,但是当我这样做时,至少我可以幸灾乐祸:
R> dason <- function(x) { numformat <- function(val){sub("^(-?)0.", "\\1.", sprintf("%.2f", as.numeric(val)))}; gsubfn("0\\.\\d+", numformat, x) }
R> dirk <- function(x) { sapply(strsplit(gsub("^(\\d+)\\((.*)\\)$", "\\1 \\2", x), " "), function(x) sprintf("%2d(.%02d)", as.numeric(x[1]), as.numeric(x[2])*100)) }
R>
R> dason(x)
[1] "20(.23)" "15(.20)" "16(.09)"
R> dirk(x)
[1] "20(.23)" "15(.20)" "16(.09)"
R>
R> res <- benchmark(dason(x), dirk(x), replications=1000, order="relative")
R> res
test replications elapsed relative user.self sys.self user.child sys.child
2 dirk(x) 1000 0.133 1.000 0.132 0.000 0 0
1 dason(x) 1000 2.026 15.233 1.960 0.064 0 0
R>
所以这大约快了 15 分钟。在这种情况下,这并不重要,但从长远来看,速度永远不会伤害任何人。