Concatenate Vector of Vector with differents length

Consider the following vector:

v = [
    (1, [[11, 11, 11], [12, 12, 12]]),
    (2, [[21, 21, 21]),
    (3, [[31, 31, 31], [32, 32, 32]]),
    (4, [[41, 41, 41]),
]

I want to get

4-element Vector{Any}:
[[11, 11, 11], [21, 21, 21], [31, 31, 31], [41, 41, 41]]
[[11, 11, 11], [21, 21, 21], [32, 32, 32], [41, 41, 41]]
[[12, 12, 12], [21, 21, 21], [31, 31, 31], [41, 41, 41]]
[[12, 12, 12],  [21, 21, 21], [32, 32, 32], [41, 41, 41]]

When all row of the vector v have same length, there is a code from @rafael.guerra .

re = Vector{Vector{Int64}}[]
n = length(v[1][2])
for i in 1:n, k in 1:n
    res = Vector{Int64}[]
    push!(res, copy(v[1][2][k]))
    for j in 2:length(v)
        push!(res, copy(v[j][2][i]))
    end
    push!(re, res)
end

You Input v is this:

julia> v = [
           (1, [[11, 11, 11], [12, 12, 12]]),
           (2, [[21, 21, 21]]),
           (3, [[31, 31, 31], [32, 32, 32]]),
           (4, [[41, 41, 41]]),
       ]
4-element Vector{Tuple{Int64, Vector{Vector{Int64}}}}:
 (1, [[11, 11, 11], [12, 12, 12]])
 (2, [[21, 21, 21]])
 (3, [[31, 31, 31], [32, 32, 32]])
 (4, [[41, 41, 41]])

?

julia> collect.(vec(collect(Iterators.product(last.(v)...))))
4-element Vector{Vector{Vector{Int64}}}:
 [[11, 11, 11], [21, 21, 21], [31, 31, 31], [41, 41, 41]]
 [[12, 12, 12], [21, 21, 21], [31, 31, 31], [41, 41, 41]]
 [[11, 11, 11], [21, 21, 21], [32, 32, 32], [41, 41, 41]]
 [[12, 12, 12], [21, 21, 21], [32, 32, 32], [41, 41, 41]]

(trick is to use outer product of all four arrays in input - this isn’t in the exact order, but you mentioned it doesn’t matter)

3 Likes

I like functional solutions better (like Dan’s).
But if you like loops, here are some

res=[]
for i1 in eachindex(last.(v)[1])
  for i2 in eachindex(last.(v)[2])
    for i3 in eachindex(last.(v)[3])
      for i4 in eachindex(last.(v)[4])
        push!(res,getindex.(last.(v), [i1,i2,i3,i4]))
      end
    end
  end
end

yes, it is the right one

This is how I thought about it. The approach is similar to Dan’s.

julia> v = [
           (1, [[11, 11, 11], [12, 12, 12]]),
           (2, [[21, 21, 21]]),
           (3, [[31, 31, 31], [32, 32, 32]]),
           (4, [[41, 41, 41]]),
       ]
4-element Vector{Tuple{Int64, Vector{Vector{Int64}}}}:
 (1, [[11, 11, 11], [12, 12, 12]])
 (2, [[21, 21, 21]])
 (3, [[31, 31, 31], [32, 32, 32]])
 (4, [[41, 41, 41]])

julia> vv = last.(v)
4-element Vector{Vector{Vector{Int64}}}:
 [[11, 11, 11], [12, 12, 12]]
 [[21, 21, 21]]
 [[31, 31, 31], [32, 32, 32]]
 [[41, 41, 41]]

julia> cis = CartesianIndices((length.(vv)...,))
CartesianIndices((2, 1, 2, 1))

julia> collect(cis)
2×1×2×1 Array{CartesianIndex{4}, 4}:
[:, :, 1, 1] =
 CartesianIndex(1, 1, 1, 1)
 CartesianIndex(2, 1, 1, 1)

[:, :, 2, 1] =
 CartesianIndex(1, 1, 2, 1)
 CartesianIndex(2, 1, 2, 1)

julia> map(cis[[1,3,2,4]]) do ci
           getindex.(last.(v), Tuple(ci))
       end
4-element Vector{Vector{Vector{Int64}}}:
 [[11, 11, 11], [21, 21, 21], [31, 31, 31], [41, 41, 41]]
 [[11, 11, 11], [21, 21, 21], [32, 32, 32], [41, 41, 41]]
 [[12, 12, 12], [21, 21, 21], [31, 31, 31], [41, 41, 41]]
 [[12, 12, 12], [21, 21, 21], [32, 32, 32], [41, 41, 41]]
2 Likes

This works for me. Thanks

function cartesian_product(v)
    res = []
    g = collect(Iterators.product(last.(v)...))
    for gi in g
        push!(res, gi)
    end
    return res
end

A slightly shorter version of @Dan 's answer

Iterators.product(last.(v)...) .|> collect |> vec

this is not correct

eachcol.(last(accumulate((s,c)->hcat.(s,c), lv[2:end], init=permutedims(lv[1]))))[:]

this should be better

eachcol.(reduce((s,c)->hcat.(reshape(s,1,:),c), last.(v)))[:]