生成随机字符串

Posted

技术标签:

【中文标题】生成随机字符串【英文标题】:Generating Random Strings 【发布时间】:2017-08-01 18:03:18 【问题描述】:

我想通过以下方式:ABCDE1234E,即每个字符串包含 5 个字符,4 个数字,然后是 1 个字符。

我想出了一种使用以下代码创建它的方法。

library(random)
string_5 <- as.vector(randomStrings(n=5000, len=5, digits=FALSE, upperalpha=TRUE,
                        loweralpha=FALSE, unique=TRUE, check=TRUE))
number_4 <- as.vector(randomNumbers(n=5000, min=1111, max=9999, col=5, base=10, check=TRUE))
string_1 <- as.vector(randomStrings(n=5000, len=1, digits=FALSE, upperalpha=TRUE,
                         loweralpha=FALSE, unique=FALSE, check=TRUE))
PAN.Number <- paste(string_5,number_4,string_1,sep = "")

但是这些功能需要很长时间,random 库需要网络连接。

> system.time(string_5 <- as.vector(randomStrings(n=5000, len=5, digits=FALSE, upperalpha=TRUE,
+                                                 loweralpha=FALSE, unique=TRUE, check=TRUE)))
   user  system elapsed 
   0.07    0.00    3.18 

有什么方法可以减少执行时间吗? 我也尝试过使用sample(),但我想不通。

【问题讨论】:

【参考方案1】:

使用@akrun 建议的“stringi”会更快,但以下也很快,不需要任何额外的包:

myFun <- function(n = 5000) 
  a <- do.call(paste0, replicate(5, sample(LETTERS, n, TRUE), FALSE))
  paste0(a, sprintf("%04d", sample(9999, n, TRUE)), sample(LETTERS, n, TRUE))

示例输出:

myFun(10)
##  [1] "BZHOF3737P" "EPOWI0674X" "YYWEB2825M" "HQIXJ5187K" "IYIMB2578R"
##  [6] "YSGBG6609I" "OBLBL6409Q" "PUMAL5632D" "ABRAT4481L" "FNVEN7870Q"

【讨论】:

【参考方案2】:

我们可以从stringi使用stri_rand_strings

library(stringi)
sprintf("%s%s%s", stri_rand_strings(5, 5, '[A-Z]'),
      stri_rand_strings(5, 4, '[0-9]'), stri_rand_strings(5, 1, '[A-Z]'))

或者更简洁

do.call(paste0, Map(stri_rand_strings, n=5, length=c(5, 4, 1),
            pattern = c('[A-Z]', '[0-9]', '[A-Z]')))

基准测试

system.time(
    do.call(paste0, Map(stri_rand_strings, n=5000, length=c(5, 4, 1),
            pattern = c('[A-Z]', '[0-9]', '[A-Z]')))
    )
#  user  system elapsed 
#   0      0      0

使用 OP 的方法,即使是预期输出的一部分,也能够重现时序

system.time(string_5 <- as.vector(randomStrings(n=5000, len=5, digits=FALSE, upperalpha=TRUE,
                                              loweralpha=FALSE, unique=TRUE, check=TRUE)))
#  user  system elapsed 
#   0.86    0.24    5.52 

【讨论】:

【参考方案3】:

您可以直接执行您想要的操作: 随机抽样 5 个大写字母 示例 4 位数 样本 1 个随机大写字母

digits = 0:9
createRandString<- function() 
  v = c(sample(LETTERS, 5, replace = TRUE),
        sample(digits, 4, replace = TRUE),
        sample(LETTERS, 1, replace = TRUE))
  return(paste0(v,collapse = ""))

这将更容易控制,并且不会花费很长时间。

【讨论】:

【参考方案4】:

您的性能问题首先来自使用random 包:您可以在互联网搜索中找到random::randomStrings() 函数并认为这是生成随机字符串以供程序使用的好方法,这是可以理解的,但random不适用于通用编程。它通过查询RANDOM.ORG 服务器来工作,这本质上比 R 的内置伪随机数生成器要慢。

来自vignettes from the random package之一:

在许多情况下,最好使用非确定性确定的 随机数。示例包括 - 使用真正独立的种子在不同节点上播种分布式计算; - 获得不依赖于特定操作系统的 RNG 的可移植初始化 或硬件功能; - 使用非确定性随机数验证模拟结果; - 提供用于抽奖或游戏的不确定种子...

请注意,这些示例中的大多数都是关于播种初始化(这些是同义词)R的内置伪随机数生成器,而不是替换它们...

【讨论】:

【参考方案5】:

如果有人来这里寻找生成随机文件名的方法,这就是我使用的方法。我喜欢它的优雅

library(dplyr)
runif(1, 1000000000000, 9999999999999) %>% round %>% as.character %>% paste0("/tmp/", ., ".png") 

注意:您可以通过将runif() 中的1 更改为您想要的数字来轻松更改它生成的随机字符串的数量

【讨论】:

【参考方案6】:

我们现在可以使用 dplyr 中的“rowwise”和“mutate”以及 stri_rand_strings 函数的 library(stringi) 来做到这一点:

df %>% 
rowwise() %>% 
mutate(unique_id = paste0(stri_rand_strings(1, 5, "[A-Z]"), stri_rand_strings(1, 4, "[0-9]"), stri_rand_strings(1, 1, "[A-Z]")))

这避免了创建函数的需要。

【讨论】:

【参考方案7】:

您可以使用 ASCII 表对最终字符串进行精细控制。

randString <- function(characters=0, numbers=0, symbols=0, lowerCase=0, upperCase=0) 
  ASCII <- NULL
  if(symbols>0)    ASCII <- c(ASCII, sample(c(33:47, 58:34, 91:96, 123:126), symbols))
  if(numbers>0)    ASCII <- c(ASCII, sample(48:57, numbers))
  if(upperCase>0)  ASCII <- c(ASCII, sample(65:90, upperCase))
  if(lowerCase>0)  ASCII <- c(ASCII, sample(97:122, lowerCase))
  if(characters>0) ASCII <- c(ASCII, sample(c(65:90, 97:122), characters))
  
  return( rawToChar(as.raw(sample(ASCII, length(ASCII)))) )

例子:

randString(characters=5, numbers=4)
# [1] "9fKW75o1N"

【讨论】:

以上是关于生成随机字符串的主要内容,如果未能解决你的问题,请参考以下文章

java怎么随机生成一个字符串?

Java随机生成字符串

C语言 如何随机生成字符串

如何用VB.NET生成一个随机字符串

MySQL生成随机字符串的三种方法

python生成随机数随机字符串