From c4f27373096d9f2e57e64235577d74aa49c989d5 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 4 Jul 2017 17:43:12 +0200 Subject: [PATCH] randstring: allow specifying chars to pick from (#22222) --- base/docs/helpdb/Base.jl | 18 ------------------ base/random.jl | 37 ++++++++++++++++++++++++++++++++----- test/random.jl | 20 ++++++++++++++++++++ 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index c26f686a4e73e..02e228114cd8e 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -766,24 +766,6 @@ julia> a """ select! -""" - randstring([rng,] len=8) - -Create a random ASCII string of length `len`, consisting of upper- and -lower-case letters and the digits 0-9. The optional `rng` argument -specifies a random number generator, see [Random Numbers](@ref). - -# Example - -```jldoctest -julia> rng = MersenneTwister(1234); - -julia> randstring(rng, 4) -"mbDd" -``` -""" -randstring - """ Float64(x [, mode::RoundingMode]) diff --git a/base/random.jl b/base/random.jl index 4375a3c7ea1ee..bb870ac8cb7d1 100644 --- a/base/random.jl +++ b/base/random.jl @@ -1618,15 +1618,42 @@ end Base.show(io::IO, u::UUID) = write(io, Base.repr(u)) # return a random string (often useful for temporary filenames/dirnames) + +""" + randstring([rng=GLOBAL_RNG], [chars], [len=8]) + +Create a random string of length `len`, consisting of characters from +`chars`, which defaults to the set of upper- and lower-case letters +and the digits 0-9. The optional `rng` argument specifies a random +number generator, see [Random Numbers](@ref). + +# Examples +```jldoctest +julia> srand(0); randstring() +"c03rgKi1" + +julia> randstring(MersenneTwister(0), 'a':'z', 6) +"wijzek" + +julia> randstring("ACGT") +"TATCGGTC" +``` + +!!! note + `chars` can be any collection of characters, of type `Char` or + `UInt8` (more efficient), provided [`rand`](@ref) can randomly + pick characters from it. +""" +function randstring end + let b = UInt8['0':'9';'A':'Z';'a':'z'] global randstring - randstring(r::AbstractRNG, n::Int) = String(b[rand(r, 1:length(b), n)]) - randstring(r::AbstractRNG) = randstring(r,8) - randstring(n::Int) = randstring(GLOBAL_RNG, n) - randstring() = randstring(GLOBAL_RNG) + randstring(r::AbstractRNG, chars=b, n::Integer=8) = String(rand(r, chars, n)) + randstring(r::AbstractRNG, n::Integer) = randstring(r, b, n) + randstring(chars=b, n::Integer=8) = randstring(GLOBAL_RNG, chars, n) + randstring(n::Integer) = randstring(GLOBAL_RNG, b, n) end - # Fill S (resized as needed) with a random subsequence of A, where # each element of A is included in S with independent probability p. # (Note that this is different from the problem of finding a random diff --git a/test/random.jl b/test/random.jl index 9439d12675e99..ca5946cb50dae 100644 --- a/test/random.jl +++ b/test/random.jl @@ -543,3 +543,23 @@ let r = MersenneTwister(0) @inferred Base.Random.reserve_1(r) @inferred Base.Random.reserve(r, 1) end + +# test randstring API +let b = ['0':'9';'A':'Z';'a':'z'] + for rng = [[], [MersenneTwister(0)]] + @test length(randstring(rng...)) == 8 + @test length(randstring(rng..., 20)) == 20 + @test issubset(randstring(rng...), b) + for c = ['a':'z', "qwèrtï", Set(Vector{UInt8}("gcat"))], + len = [8, 20] + s = len == 8 ? randstring(rng..., c) : randstring(rng..., c, len) + @test length(s) == len + if eltype(c) == Char + @test issubset(s, c) + else # UInt8 + @test issubset(s, map(Char, c)) + end + end + end + @test randstring(MersenneTwister(0)) == randstring(MersenneTwister(0), b) +end