Grid of all elements of an arbitrarily sized matrix

I have an n*m sized array A, and I would like to create a grid of its elements. The output should look something like:

B = (A[1,1], A[2,1]
     A[1,1], A[2,2]
     ...
     A[1,1], A[2,m]
     A[1,2], A[2,1]
     A[1,2], A[2,2]
     ...
     A[1,2], A[2,m]
     ...
     A[n,1], A[n,m])

My first approach would be to do something like this:

A = [1 5;
     2 6;
     3 7;
     4 8]

B = collect(Iterators.product(A))

However, this only returns

4×2 Matrix{Tuple{Int64}}:
 (1,)  (5,)
 (2,)  (6,)
 (3,)  (7,)
 (4,)  (8,)

Instead of the desired output above.

Any ideas?

I guess you want something along the lines of

julia> Iterators.product(A[:, 1], A[:, 2]) |> collect
4×4 Matrix{Tuple{Int64, Int64}}:
 (1, 5)  (1, 6)  (1, 7)  (1, 8)
 (2, 5)  (2, 6)  (2, 7)  (2, 8)
 (3, 5)  (3, 6)  (3, 7)  (3, 8)
 (4, 5)  (4, 6)  (4, 7)  (4, 8)

Tweak shape etc. as needed.

1 Like

Thanks for the suggestion. But this only reshapes the array. But what I need is a bit different.
Let me give you an example:

A = [1 5;
     2 6;
     3 7;
     4 8]

And the result should be:

B = [1 5;
     1 6;
     1 7;
     1 8;
     2 5;
     2 6;
     2 7;
     2 8;
     3 5;
     3 6;
     3 7;
     3 8;
     4 5;
     4 6;
     4 7;
     4 8;]

I could write it in a nested loop but it should be able to handle arrays of any n*m.
The Iterator.product() function is promising but I do not know how to get it to work with a matrix. It does work with separate vectors though. And I don’t know how to make it work without inputting a fixed amount of vectors.

Thanks! That’s what I also thought. I just need to be able to make the

A[:, 1], A[:, 2]

flexible. So, I need to be able to input a matrix with any number of columns.

This should work, though I’m unsure if it is efficient:

Iterators.product(eachcol(A)...) |> collect

If you want one tall vector, just pass it into vec:

Iterators.product(eachcol(A)...) |> collect |> vec
2 Likes

That works. Awesome, thanks!
Can you just quickly explain what the three dots do?

Sorry, I just switched to Julia.

The three dots, the splatting operator, unpacks a collection of elements into a list of arguments.

For example, if you have a function, foo(x, y) that takes two arguments, you cannot call it like this: foo([1, 2]). But you can unpack the elements from the array into two arguments: foo([1, 2]...)

You can read docstrings for operators and functions like this:

julia> ?  # type question mark. The prompt turns into

help?> ...  # type the operator you are wondering about, like ...
search: ...

  ...


  The "splat" operator, ..., represents a sequence of arguments. ... can be used  
  in function definitions, to indicate that the function accepts an arbitrary     
  number of arguments. ... can also be used to apply a function to a sequence of  
  arguments.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

(The same syntax is used for “slurping”, which is sort of the opposite.)

1 Like

That makes sense. Thanks!