Suppose I have some number of iterables, and I want to turn their product into a matrix, with one column per iterable. I've gotten close with the following:
julia> x = 1:3; y = 4:10; z = 10:5:30;
julia> reduce(vcat, Iterators.product(x,y,z))
105-element Vector{Tuple{Int64, Int64, Int64}}:
(1, 4, 10)
(2, 4, 10)
(3, 4, 10)
(1, 5, 10)
(2, 5, 10)
# ...
But now I need to get that into a matrix. I can hack something together with Iterators.flatten
and a reshape
, but it's... um... not pretty
julia> function make_matrix(args...)
permutedims(reshape(collect(Iterators.flatten(reduce(vcat, Iterators.product(args...)))),
length(args), *(length.(args)...)))
end
make_matrix (generic function with 1 method)
julia> make_matrix(x,y,z)
105×3 Matrix{Int64}:
1 4 10
2 4 10
3 4 10
1 5 10
2 5 10
3 5 10
1 6 10
2 6 10
3 6 10
1 7 10
you can use collect(Iterators.product(x, y, z))
best I can come up with, but it's also ugly
permutedims(reduce(hcat,map(x->[x...],Iterators.product(x,y,z))))
@Takafumi Arakaki (tkf) That give you a 3D Array:
julia> collect(Iterators.product(x,y,z))
3×7×5 Array{Tuple{Int64, Int64, Int64}, 3}:
@Maarten Oh, that's clever :-)
you can get it slightly shorter using mapreduce, which I forgot about x)
transpose(reinterpret(reshape, Int, vec(collect(Iterators.product(x,y,z)))))
is probably quite efficient.
Or using TensorCast; @cast out[(i,j,k),c] := (x[i], y[j], z[k])[c] c in 1:3
Oops, sorry I misread the question. And yeah, for a quick code, I'd use reinterpret
like Michael does.
A variant of this is to do the reshape on the receiver side:
m = Matrix{Int}(undef, prod(length, (x, y, z)), 3)
reshape(reinterpret(Tuple{Int,Int,Int}, vec(m')), length.((x, y, z))) .= tuple.(reshape(x, :, 1, 1), reshape(y, 1, :, 1), reshape(z, 1, 1, :))
(which could be useful if you want contiguous memory as a result and avoid copy)
Probably not very efficient, but a concise one-liner:
julia> Matrix(DataFrame(Iterators.product(x, y, z)))
105×3 Matrix{Int64}:
1 4 10
2 4 10
...
Nice idea about DataFrames. Extending this idea we can get the following
julia> Tables.matrix(Iterators.product(x, y, z))
105×3 Matrix{Int64}:
1 4 10
2 4 10
...
Last updated: Dec 28 2024 at 04:38 UTC