-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
add rand(::String) #22224
Changes from 1 commit
459a126
1deb0c5
5e827e9
533dfb3
3b97b61
fa51ee6
a5289a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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), | ||
* 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; | ||
|
@@ -709,6 +710,44 @@ 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 | ||
|
||
rand(rng::AbstractRNG, s::AbstractString) = rand_iter(rng, s, Base.iteratorsize(s)) | ||
rand(s::AbstractString) = rand(GLOBAL_RNG, s) | ||
|
||
## optimization for String | ||
|
||
isvalid_unsafe(s::String, i) = !Base.is_valid_continuation(unsafe_load(pointer(s), i)) | ||
|
||
function rand(rng::AbstractRNG, s::String) | ||
rg = Base.Random.RangeGenerator(1:s.len) | ||
while true | ||
pos = rand(Base.Random.GLOBAL_RNG, rg) | ||
isvalid_unsafe(s, pos) && return s[pos] | ||
end | ||
end | ||
|
||
## rand from an iterator | ||
|
||
rand_iter(rng, s, ::Base.IteratorSize) = throw(ArgumentError("iterator must have a known length")) | ||
|
||
function rand_iter(rng::AbstractRNG, s, ::Union{Base.HasShape,Base.HasLength})::eltype(s) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, why is the return type annotation necessary here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. inference probably can't determine that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes Tony is spot on, and also initially I thought to propose this PR working generally on iterators, and the return type annotation could serve as an additional way to check whether the argument was complying to the iterator interface. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, nice. Thanks for the explanation, both of you. |
||
pos = rand(rng, 1:length(s)) | ||
for (i, c) in enumerate(s) | ||
i == pos && return c | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a little skeptical of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes I agree, I had the same hesitation and had planned to update the doc today to warn about the complexity. Then I think that with a proper warning those convenience methods (similarly for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could also do rejection sampling: randomly choose and index from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh great! for some reason, I skimmed too fast on the generic code of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I was confused not about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @StefanKarpinski would you mind having a look at this updated generic implementation, to confirm it complies with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better to do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok thanks (I believe the idea being that |
||
|
||
## 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) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need "or" at the end of this line (or at the beginning of the next line)