3

I'm trying to do the following in a general way:

x = {0:1, 2:3, 4:6};
[a,b,c] = ndgrid(x{:});
Res = [a(:), b(:), c(:)]
Res =
   0   2   4
   1   2   4
   0   3   4
   1   3   4
   0   2   5
   1   2   5
   0   3   5
   1   3   5
   0   2   6
   1   2   6
   0   3   6
   1   3   6

I believe I have to start the following way, but I can't figure out how to continue:

cell_grid = cell(1,numel(x));
[cell_grid{:}] = ndgrid(x{:});
[cell_grid{:}]
ans =    
ans(:,:,1) =
   0   0   2   3   4   4
   1   1   2   3   4   4
ans(:,:,2) =
   0   0   2   3   5   5
   1   1   2   3   5   5
ans(:,:,3) =
   0   0   2   3   6   6
   1   1   2   3   6   6

I can solve this in many ways for the case with three variables [a, b, c], both with and without loops, but I start to struggle when I get more vectors. Reshaping it directly will not give the correct result, and mixing reshape with permute becomes really hard when I have arbitrary number of dimensions.

Can you think of a clever way to do this that scales to 3-30 vectors in x?

Stewie Griffin
  • 14,889
  • 11
  • 39
  • 70

1 Answers1

2

You can use cellfun to flatten each of the cell array elements and then concatenate them along the second dimension.

tmp = cellfun(@(x)x(:), cell_grid, 'uniformoutput', false);
out = cat(2, tmp{:})

Alternately, you could avoid cellfun and concatenate them along the dimension that is one higher than your dimension of each cell_grid member (i.e. numel(x) + 1). Then reshape to flatten all dimensions but the last one you just concatenated along.

out = reshape(cat(numel(x) + 1, cell_grid{:}), [], numel(x));
Suever
  • 64,497
  • 14
  • 82
  • 101