生成唯一的字母数字ID

Jul*_*rre 3 r

我有一个数据框,我想添加一个包含不重复的字母数字值的列.

首先,我改编了一个我在博客上找到的功能.(https://ryouready.wordpress.com/2008/12/18/generate-random-string-name/)

idGenerator <- function(n, lengthId) {

  alphaNum <- c(0:9, letters, LETTERS)

  if (n > length(alphaNum)^lengthId) {
    return("Error! n > perms : Infinite loop")
  }

  idList <- rep(NULL, n)

  for (i in 1:n) {
    idList[i] <- paste(sample(alphaNum, 
                                    lengthId, replace = TRUE), collapse = "")
    while(idList[i] %in% idList[-i]) {
      idList[i] <- paste(sample(alphaNum, 
                                lengthId, replace = TRUE), collapse = "")
    }
  }

  return(idList)
}
Run Code Online (Sandbox Code Playgroud)

我的问题是我的数据帧有大约250k行,所以n = 250k这个函数只是永远运行.我知道n = 250k,如果我增加id字符串的长度(lengthId)获得相同字符串的几率是不现实的,所以while循环是浪费资源,但我真的需要确保不会发生,我对控制结构意味着"肯定".

所以我发现了一种更有效的方法,而不是调用while并检查i循环中每个的所有向量,我检查最终向量中是否有重复:

idGenerator <- function(n, lengthId) {

  alphaNum <- c(0:9, letters, LETTERS)

  if (n > length(alphaNum)^lengthId) {
    return("Error! n > perms : Infinite loop")
  }

  idList <- 1:n

  for (i in 1:n) {
    idList[i] <- paste(sample(alphaNum, 
                              lengthId, replace = TRUE), collapse = "")
  }

  while(any(duplicated(idList))) {
    idList[which(duplicated(idList))] <- paste(sample(alphaNum, lengthId, 
                                                replace = TRUE), collapse = "")
  }

  return(idList)
}
Run Code Online (Sandbox Code Playgroud)

如果while必须运行很多次,这是非常慢的=>当n非常接近排列的数量时.

> system.time(idGenerator(62^2, 2))
    utilisateur     système     écoulé 
    8.00            0.00        8.02 

 > system.time(idGenerator(62^3, 3))

 Timing stopped at: 584.35 16.66 602.46
Run Code Online (Sandbox Code Playgroud)

但是对于长id字符串来说这是完全可以接受的:

> system.time(idGenerator(250000, 12))
    utilisateur     système     écoulé 
    3.2             0.0         3.2 
Run Code Online (Sandbox Code Playgroud)

然而,创建一个列仍然是3秒+所以我正在寻找一种更快的方式.我知道循环不是那么好,我应该更喜欢矢量化,但我不是真正的代码优化大师.所以,如果您有任何想法,请提前感谢您.

A5C*_*2T1 10

我建议stri_rand_strings从"stringi"包中查看函数:

library(stringi)
stri_rand_strings(10, 3)
 # [1] "wsm" "FvH" "UXm" "14t" "rvv" "Pfo" "mzK" "20b" "O9P" "ZOr"
system.time(X <- stri_rand_strings(250000, 12))
#    user  system elapsed 
#   0.327   0.003   0.333 
length(unique(X))
# [1] 250000
head(X)
# [1] "WxRPZjt0uFaI" "E129Ug0Vif3f" "qXGzQDO0LzvG" 
# [4] "9D4guGMf2jZ1" "Qw1p7reH4XKg" "0gziFNnZ16p8"
Run Code Online (Sandbox Code Playgroud)

  • 这么好的功能,我以前都不知道。谢谢。我刚刚添加了重复的控件: `idGenerator &lt;- function(n, lengthId) { idList &lt;- stringi::stri_rand_strings(n, lengthId, pattern = "[A-Za-z0-9]") while(any(duplicated( idList))) { idList[which(duplicated(idList))] &lt;- stringi::stri_rand_strings(sum(duplicated(idList), na.rm = TRUE), lengthId, pattern = "[A-Za-z0-9] ") } 返回(idList) }` (2认同)