我正在寻找一种有效的方法来为我正在生成的一些合成数据创建唯一的数字ID.
现在,我只是有一个函数可以从全局变量中发出并递增一个值(参见下面的演示代码).但是,这很麻烦,因为我必须初始化idCounter
变量,如果可能的话我宁愿不使用全局变量.
# Emit SSN
idCounter = 0
emitID = function(){
# Turn into a formatted string
id = formatC(idCounter,width=9,flag=0,format="d")
# Increment id counter
idCounter <<- idCounter+1
return(id)
}
record$id = emitID()
Run Code Online (Sandbox Code Playgroud)
该uuid
软件包提供了接近我想要的功能,但我只需要ID为整数.有什么建议?也许是一种将UUID值转换为某种数值的方法?显然会发生一些碰撞,但这可能没问题.我想,最多,我需要10亿个价值观.
谢谢你的任何建议!
-抢
Mar*_*gan 22
计数器的非全局版本使用词法范围来封装idCounter
增量函数
emitID <- local({
idCounter <- -1L
function(){
idCounter <<- idCounter + 1L # increment
formatC(idCounter, width=9, flag=0, format="d") # format & return
}
})
Run Code Online (Sandbox Code Playgroud)
然后
> emitID()
[1] "000000000"
> emitID1()
[1] "000000001"
> idCounter <- 123 ## global variable, not locally scoped idCounter
> emitID()
[1] "000000002"
Run Code Online (Sandbox Code Playgroud)
一个有趣的选择是使用"工厂"模式来创建独立的计数器.你的问题意味着你将这个函数称为十亿(嗯,不确定我在哪里得到那个印象......)次,所以也许通过创建一个id的缓冲区来对formatC的调用进行矢量化是有意义的吗?
idFactory <- function(buf_n=1000000) {
curr <- 0L
last <- -1L
val <- NULL
function() {
if ((curr %% buf_n) == 0L) {
val <<- formatC(last + seq_len(buf_n), width=9, flag=0, format="d")
last <<- last + buf_n
curr <<- 0L
}
val[curr <<- curr + 1L]
}
}
emitID2 <- idFactory()
Run Code Online (Sandbox Code Playgroud)
然后(emitID1
是上面的局部变量版本的实例).
> library(microbenchmark)
> microbenchmark(emitID1(), emitID2(), times=100000)
Unit: microseconds
expr min lq median uq max neval
emitID1() 66.363 70.614 72.310 73.603 13753.96 1e+05
emitID2() 2.240 2.982 4.138 4.676 49593.03 1e+05
> emitID1()
[1] "000100000"
> emitID2()
[1] "000100000"
Run Code Online (Sandbox Code Playgroud)
(原型解决方案比emitID1
速度快3倍,但速度不是一切).
我喜欢使用该proto
软件包进行小型OO编程.在引擎盖下,它使用的环境与Martin Morgan所说的类似.
# this defines your class
library(proto)
Counter <- proto(idCounter = 0L)
Counter$emitID <- function(self = .) {
id <- formatC(self$idCounter, width = 9, flag = 0, format = "d")
self$idCounter <- self$idCounter + 1L
return(id)
}
# This creates an instance (or you can use `Counter` directly as a singleton)
mycounter <- Counter$proto()
# use it:
mycounter$emitID()
# [1] "000000000"
mycounter$emitID()
# [1] "000000001"
Run Code Online (Sandbox Code Playgroud)