Reputation: 7674
What's the easiest way in Julia to call a function n
times, with the same arguments, and return the result in an array? For example, I'd like to get an array of random strings, each of a certain length. The best I've been able to come up with is
julia> map(_ -> randstring(4), 1:6)
6-element Array{String,1}:
"xBWv"
"CxJm"
"KsHk"
"UUIP"
"64o4"
"QNgm"
Another alternative is to use broadcasting, like in either of the following:
# Broadcast over an array of 4's
randstring.(fill(4, 6))
# Broadcast over an iterator that repeats the number 4 six times
using Base.Iterators
randstring.(repeated(4, 6))
However, my preference is for a syntax like replicate(randstring(4), 6)
. For comparison, in R I would do the following:
> # Sample from lower-case letters only:
> random_string <- function(n) paste(sample(letters, n, replace = TRUE), collapse = '')
> replicate(6, random_string(4))
[1] "adru" "neyf" "snuo" "xvnq" "yqfv" "gept"
Upvotes: 6
Views: 2228
Reputation: 1672
While there are ways to do this without introducing package dependencies, Lazy.jl does provide a lot of these nice, functional tools.
In particular, you said
my preference is for a syntax like replicate(randstring(4), 6)
First, note that this is no exactly "calling a function n
times, because randstring(4)
is not a function, it is evaluated.
So instead you want to call the anonymous function n
times, to align with the equation title, in which case your preferred syntax is replicate(()->randstring(4),6)
Good news! Lazy.jl
provides almost this exact syntax with the function repeatedly
. The only distinction is that it takes n
as its first argument:
repeatedly(6,()->randstring(4))
The other distinction to notice is that this returns, for other reasons, a LazyList
type, not an Array
.
Now, it's likely the case that you won't notice the difference, e.g. you can index and broadcast into the List
like you might an Array
.
However, if you don't intend on exploiting any of the nice Lazy
properties and you really do need it to be an Array
then you can just directly unpack the List
into Array
.
Here is a full example:
using Random
using Lazy
stringlist = repeatedly(6,()->randstring(4))
stringarray = [stringlist...]
Upvotes: 1
Reputation: 466
I would go with
using Random
six_randstrings = [randstring(4) for _ in 1:6]
Upvotes: 12
Reputation: 724
If you're unhappy with using map
or array comprehensions directly then you could create a macro for this:
macro replicate(ex, n)
return :(map(_ -> $(esc(ex)), 1:$(esc(n))))
end
@replicate(rand(), 4)
Upvotes: 4