Iterators product on array of arrays - julia

How can I create an iterator on the product of arrays, from an array of arrays?
The Array size not predetermined.
Basically the following works as I wish:
for i in Base.Iterators.product([1,2,3],[4,5])
print(i)
end
(1, 4)(2, 4)(3, 4)(1, 5)(2, 5)(3, 5)
But I would like it to work for an array of arrays, but I am getting different result:
x = [[1,2,3],[4,5]]
for i in Base.Iterators.product(x)
print(i)
end
([1, 2, 3],)([4, 5],)

You can use the splat operator to interpolate the array of arrays into the function call:
julia> x = [[1,2,3],[4,5]];
julia> for i in Base.Iterators.product(x...)
print(i)
end
(1, 4)(2, 4)(3, 4)(1, 5)(2, 5)(3, 5)

Related

How to append to an empty list in Julia?

I want to create an empty lsit and gardually fill that out with tuples. I've tried the following and each returns an error. My question is: how to append or add and element to an empty array?
My try:
A = []
A.append((2,5)) # return Error type Array has no field append
append(A, (2,5)) # ERROR: UndefVarError: append not defined
B = Vector{Tuple{String, String}}
# same error occues
You do not actually want to append, you want to push elements into your vector. To do that use the function push! (the trailing ! indicates that the function modifies one of its input arguments. It's a naming convention only, the ! doesn't do anything).
I would also recommend creating a typed vector instead of A = [], which is a Vector{Any} with poor performance.
julia> A = Tuple{Int, Int}[]
Tuple{Int64, Int64}[]
julia> push!(A, (2,3))
1-element Vector{Tuple{Int64, Int64}}:
(2, 3)
julia> push!(A, (11,3))
2-element Vector{Tuple{Int64, Int64}}:
(2, 3)
(11, 3)
For the vector of string tuples, do this:
julia> B = Tuple{String, String}[]
Tuple{String, String}[]
julia> push!(B, ("hi", "bye"))
1-element Vector{Tuple{String, String}}:
("hi", "bye")
This line in your code is wrong, btw:
B = Vector{Tuple{String, String}}
It does not create a vector, but a type variable. To create an instance you can write e.g. one of these:
B = Tuple{String, String}[]
B = Vector{Tuple{String,String}}() # <- parens necessary to construct an instance
It can also be convenient to use the NTuple notation:
julia> NTuple{2, String} === Tuple{String, String}
true
julia> NTuple{3, String} === Tuple{String, String, String}
true

Find length of array of functions in Julia

I want to find the length, nc, of this "vector of functions". I should be 2.
comp(x) = [([x[5], x[6], x[7], x[8],x[9], x[10]], tmp(x)) ; ([x[1],x[2]], [x[3],x[4]])];
nc = ....
I tried with length(comp) and length(comp(x)) but it doesn't work. I get "x not defined" and "no method matching length(::typeof(comp))", respectively.
Pulling together some of the comments to hopefully make things clearer:
What you have written is essentially
function comp(x)
a = [x[5], x[6], x[7], x[8],x[9], x[10]]
b = [x[1],x[2]]
c = [x[3],x[4]]
return [(a, tmp(x)); (b, c)]
end
that is, you have defined a function comp which takes one argument x and then returns a 2-element vector of 2-element tuples, with the first tuple holding values 5 to 10 of x and the result of tmp(x) (this function is not defined in your code so we don't know what it returns), and the second tuple holding the first and second, and third and fourth elements of x, respectively.
To illustrate, assume tmp(x) just sums up the elements of x, then we can pass some array (in the below example a range) of numbers to comp and see it in action:
julia> tmp(x) = sum(x)
tmp (generic function with 1 method)
julia> comp(1:20)
2-element Vector{Tuple{Vector{Int64}, Any}}:
([5, 6, 7, 8, 9, 10], 210)
([1, 2], [3, 4])
and you can get the result of the return value:
julia> length(comp(1:20))
2

Convert a vector of tuples in an array in JULIA

I'm quite new to Julia and I'm trying to convert a vector of tuples in array.
Here's an example
using Statistics
a = randn((10, 100))
q = (0.05, 0.95)
conf_intervals = [quantile(a[i,:], q) for i in 1:10]
and conf_intervals is a 10-element Vector{Tuple{Float64, Float64}}.
The expected result should be a 10×2 Matrix{Float64}
I tried splatting conf_intervals with [conf_intervals...] but the vector doesn't change.
Thank you very much
You can use a comprehension:
mat2x10 = [tup[k] for k in 1:2, tup in conf_intervals]
mat10x2 = [tup[k] for tup in conf_intervals, k in 1:2]
Or you can just re-interpret the same memory. This is more fragile -- it won't work for all vectors of tuples, e.g. Any[(i, i^2/2) for i in 1:10]. But for Vector{Tuple{Float64, Float64}}:
if VERSION >= v"1.6"
reinterpret(reshape, Float64, conf_intervals)
else
reshape(reinterpret(Float64, conf_intervals), 2, :)
end
mat2x10 == ans # true
You need to use collect to convert tuples to vectors, and then you can combine them:
julia> hcat(collect.(conf_intervals)...)
2×10 Matrix{Float64}:
-1.59757 -2.10057 -1.4437 -1.32868 -1.10686 -1.41256 -1.5696 -1.67288 -1.51947 -1.72257
1.24604 1.61692 1.77684 1.3599 1.90853 1.30831 1.10667 1.58356 1.56811 1.70685
If you need to transpose the result, add an apostrophe ' end the end of the command

unexpected behavior of dict.keys on in

for faster colision control I create dict which is used as sparse array from array of objects T2.
But this cod throw exeption
KeyError: key [142, 69, 77] not found
Here us my code:
Ans=Dict{T1,Vector{T2}}()
for i in L
pos=pos_func(i)
if (pos in Ans.keys)
push!(Ans[pos],i)
else
Ans[pos]=Vector{T2}([i])
end
end
I catched event and printed pos, Ans.keys and (pos in Ans.keys). I found that pos is one of Ans.keys and (pos in Ans.keys)==True. But anyway I cannot get Ans[pos].
Julia Version 1.4.0 Commit b8e9a9ecc6 (2020-03-21 16:36 UTC)
What is the reason for such behaviour? Why same code can works half times?
You should use the keys() function in order to get the keys of your dictionary instead of accessing the keys field. (Note that, in most cases, it is not a good idea to access internal fields of Julia objects, especially when accessor methods exist).
And in the particular case of testing whether a given key appears in a Dict, using haskey() would be even more idomatic.
The following should work:
# Some definitions so that your example is runnable
julia> T1 = Int;
julia> T2 = Int;
julia> L = 1:10;
julia> pos_func(i) = i%3;
julia> Ans=Dict{T1,Vector{T2}}()
Dict{Int64,Array{Int64,1}} with 0 entries
julia> for i in L
pos=pos_func(i)
if haskey(Ans, pos) # <- keys(Ans) instead of Ans.keys
push!(Ans[pos],i)
else
Ans[pos] = T2[i] # or maybe simply [i], unless your collection L is heterogeneous
end
end
julia> Ans
Dict{Int64,Array{Int64,1}} with 3 entries:
0 => [3, 6, 9]
2 => [2, 5, 8]
1 => [1, 4, 7, 10]

How to convert a multidimensional array to/from vector of vector of ... vector in julia

Is there a method in julia to convert a multidimensional array to a vector of vector and so on, and vice versa? It is OK to define a method for a fix number of dimensions. But how about a method for arbitrary dims?
julia> s = (1,2,3)
julia> a = reshape(1:prod(s), s)
1×2×3 Base.ReshapedArray{Int64,3,UnitRange{Int64},Tuple{}}:
[:, :, 1] =
1 2
[:, :, 2] =
3 4
[:, :, 3] =
5 6
julia> b = [[[a[i,j,k] for i=1:s[1]] for j=1:s[2]] for k=1:s[3]]
3-element Array{Array{Array{Int64,1},1},1}:
Array{Int64,1}[[1], [2]]
Array{Int64,1}[[3], [4]]
Array{Int64,1}[[5], [6]]
julia> unstack(a) == b
ERROR: UndefVarError: unstack not defined
RecursiveArrayTools.jl can help with this kind of work.
recs = [rand(8) for i in 1:10]
A = VectorOfArray(recs)
A[i] # Returns the ith array in the vector of arrays
A[j,i] # Returns the jth component in the ith array
A[j1,...,jN,i] # Returns the (j1,...,jN) component of the ith array
So it acts like the matrix without ever building the matrix, which is a good way to save allocations if you tend to act on the columns (which are the separate arrays). It also has a fast conversion to a contiguous array via the indexing fallback (honestly, I tried to create a faster one but the fallback worked better than I could make it):
arr = convert(Array,A)
Converting back would require allocating of course
VA = VectorOfArray([A[:,i] for i in size(A,2)])

Resources