Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add rand(::String) #22224

Merged
merged 7 commits into from
Jun 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Library improvements
* The function `randn` now accepts complex arguments (`Complex{T <: AbstractFloat}`)
([#21973]).

* The function `rand` can now pick up random elements from strings, associatives
and sets ([#22228], [#21960], [#18155], [#22224]).

* Method lists are now printed as a numbered list. In addition, the source code of a
method can be opened in an editor by entering the corresponding number in the REPL
and pressing `^Q` ([#22007]).
Expand Down Expand Up @@ -743,6 +746,7 @@ Command-line option changes
[#17785]: https://github.com/JuliaLang/julia/issues/17785
[#18012]: https://github.com/JuliaLang/julia/issues/18012
[#18050]: https://github.com/JuliaLang/julia/issues/18050
[#18155]: https://github.com/JuliaLang/julia/issues/18155
[#18159]: https://github.com/JuliaLang/julia/issues/18159
[#18218]: https://github.com/JuliaLang/julia/issues/18218
[#18251]: https://github.com/JuliaLang/julia/issues/18251
Expand Down Expand Up @@ -876,6 +880,7 @@ Command-line option changes
[#21759]: https://github.com/JuliaLang/julia/issues/21759
[#21818]: https://github.com/JuliaLang/julia/issues/21818
[#21825]: https://github.com/JuliaLang/julia/issues/21825
[#21960]: https://github.com/JuliaLang/julia/issues/21960
[#21973]: https://github.com/JuliaLang/julia/issues/21973
[#21974]: https://github.com/JuliaLang/julia/issues/21974
[#22007]: https://github.com/JuliaLang/julia/issues/22007
Expand All @@ -884,3 +889,7 @@ Command-line option changes
[#22064]: https://github.com/JuliaLang/julia/issues/22064
[#22187]: https://github.com/JuliaLang/julia/issues/22187
[#22188]: https://github.com/JuliaLang/julia/issues/22188
[#22224]: https://github.com/JuliaLang/julia/issues/22224
[#22228]: https://github.com/JuliaLang/julia/issues/22228
[#22245]: https://github.com/JuliaLang/julia/issues/22245
[#22310]: https://github.com/JuliaLang/julia/issues/22310
32 changes: 30 additions & 2 deletions base/random.jl
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,9 @@ globalRNG() = GLOBAL_RNG

Pick a random element or array of random elements from the set of values specified by `S`; `S` can be

* an indexable collection (for example `1:n` or `['x','y','z']`), or
* an `Associative` or `AbstractSet` object, or
* an indexable collection (for example `1:n` or `['x','y','z']`),
* an `Associative` or `AbstractSet` object,
* a string (considered as a collection of characters), or
* a type: the set of values to pick from is then equivalent to `typemin(S):typemax(S)` for
integers (this is not applicable to [`BigInt`](@ref)), and to ``[0, 1)`` for floating
point numbers;
Expand Down Expand Up @@ -709,6 +710,33 @@ end
rand(rng::AbstractRNG, r::AbstractArray{T}, dims::Dims) where {T} = rand!(rng, Array{T}(dims), r)
rand(rng::AbstractRNG, r::AbstractArray, dims::Integer...) = rand(rng, r, convert(Dims, dims))

# rand from a string

isvalid_unsafe(s::String, i) = !Base.is_valid_continuation(unsafe_load(pointer(s), i))
isvalid_unsafe(s::AbstractString, i) = isvalid(s, i)
_endof(s::String) = s.len
_endof(s::AbstractString) = endof(s)

function rand(rng::AbstractRNG, s::AbstractString)::Char
g = RangeGenerator(1:_endof(s))
while true
pos = rand(rng, g)
isvalid_unsafe(s, pos) && return s[pos]
end
end

rand(s::AbstractString) = rand(GLOBAL_RNG, s)

## rand from a string for arrays
# we use collect(str), which is most of the time more efficient than specialized methods
# (except maybe for very small arrays)
rand!(rng::AbstractRNG, A::AbstractArray, str::AbstractString) = rand!(rng, A, collect(str))
rand!(A::AbstractArray, str::AbstractString) = rand!(GLOBAL_RNG, A, str)
rand(rng::AbstractRNG, str::AbstractString, dims::Dims) = rand!(rng, Array{eltype(str)}(dims), str)
rand(rng::AbstractRNG, str::AbstractString, d1::Integer, dims::Integer...) = rand(rng, str, convert(Dims, tuple(d1, dims...)))
rand(str::AbstractString, dims::Dims) = rand(GLOBAL_RNG, str, dims)
rand(str::AbstractString, d1::Integer, dims::Integer...) = rand(GLOBAL_RNG, str, d1, dims...)

## random BitArrays (AbstractRNG)

function rand!(rng::AbstractRNG, B::BitArray)
Expand Down
19 changes: 12 additions & 7 deletions test/random.jl
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,9 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()])
1:100 => Int,
rand(Int, 100) => Int,
Int => Int,
Float64 => Float64]

Float64 => Float64,
"qwèrtï" => Char,
GenericString("qwèrtï") => Char]
b2 = big(2)
u3 = UInt(3)
for f in [rand, randn, randexp]
Expand All @@ -346,10 +347,13 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()])
a0 = rand(rng..., C) ::T
a1 = rand(rng..., C, 5) ::Vector{T}
a2 = rand(rng..., C, 2, 3) ::Array{T, 2}
a3 = rand(rng..., C, b2, u3) ::Array{T, 2}
a4 = rand!(rng..., Array{T}(5), C) ::Vector{T}
a5 = rand!(rng..., Array{T}(2, 3), C) ::Array{T, 2}
for a in [a0, a1..., a2..., a3..., a4..., a5...]
a3 = rand(rng..., C, (2, 3)) ::Array{T, 2}
a4 = rand(rng..., C, b2, u3) ::Array{T, 2}
a5 = rand!(rng..., Array{T}(5), C) ::Vector{T}
a6 = rand!(rng..., Array{T}(2, 3), C) ::Array{T, 2}
@test size(a1) == (5,)
@test size(a2) == size(a3) == (2, 3)
for a in [a0, a1..., a2..., a3..., a4..., a5..., a6...]
if C isa Type
@test a isa C
else
Expand All @@ -358,7 +362,8 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()])
end
end
for C in [1:0, Dict(), Set(), IntSet(), Int[],
GenericDict(Dict()), GenericSet(Set())]
GenericDict(Dict()), GenericSet(Set()),
"", Base.Test.GenericString("")]
@test_throws ArgumentError rand(rng..., C)
@test_throws ArgumentError rand(rng..., C, 5)
end
Expand Down