4

I have a simple question but I can't figure it out or find it anywhere. I have a cell array where c{1} is a vector and c{2} is a vector but of different lengths, up to c{i}. What I want is one vector that is [c{1};c{2};c{3}...c{i}]. What is the most efficient way to do this?

Elliot Gorokhovsky
  • 3,610
  • 2
  • 31
  • 56
  • if the c{1},... vectors are with different lengths, you cannot gather them all in one vector/Matrix. because making a matrix from some vectors needs that those vectors be the same size. – NKN Jan 02 '14 at 20:32
  • I actually figured out how to do it by individually adding each vector to the big vector as they were created. – Elliot Gorokhovsky Jan 02 '14 at 20:42
  • It is possible to take vectors of different lengths into one vector. If you have [1,2] and [3,4,5] you can put them together into [1,2,3,4,5] – Elliot Gorokhovsky Jan 02 '14 at 20:42
  • what you mentioned in your post is not like this example, [c{1};c{2};c{3}...c{i}], here you are actually adding each vector in one row that makes it impossible using vectors with different length. – NKN Jan 02 '14 at 21:21
  • 1
    possible duplicate of [How can I accumulate cells of different lengths into a matrix in MATLAB?](http://stackoverflow.com/questions/3054437/how-can-i-accumulate-cells-of-different-lengths-into-a-matrix-in-matlab) – John Jan 02 '14 at 21:30
  • @John its not really a duplicate. The OP wants a vector, not a matrix filled with `NaN`s. – Robert Seifert Jan 03 '14 at 09:58
  • It helps to specify whether you're using Matlab or Octave. They have some subtle and some not so subtle differences. – Charity Leschinski Jan 03 '14 at 15:47

5 Answers5

3

The following one-liner even works for completely inconsistent inputs:

result = [cell2mat(cellfun(@(x) x(:), A, 'uni', 0)')]'

Example:

for:

A{1} = [1, 2, 3, 4, 5];
A{2} = [6; 7; 8; 9];
A{3} = [10, 12; 11, 13];

it returns:

result =

     1     2     3     4     5     6     7     8     9    10    11    12    13
Robert Seifert
  • 25,078
  • 11
  • 68
  • 113
2

Matlab/Octave allows this king of really-not-efficient but very-convenient notation, assuming a is a structure only containing column-vectors:

x = [];             #% A fresh new vector/matrix/tensor, who knows?
for i=1:numel(a)    #% parse container item by item
   x = [x;a{i}];    #% append container item a{i} to x in a column-fashion way
end

This will works but it is bloody inefficient since it will reallocate x each for step and it is not bulletproof (no error handling, no type checking): therefore it will fail if it encounters anything (matrix, string, row vector) but column vector which are likely to be found in such containers.

Anyway, it will ease a not-so-stringent-and-heuristic design, but please consider reimplementing when robust design is needed.

jlandercy
  • 7,183
  • 1
  • 39
  • 57
  • Ya that's basically how I ended up doing it. The only difference is I added to x as each element of a was created instead of doing it all at once but the time was the same. – Elliot Gorokhovsky Jan 02 '14 at 21:31
  • Your solution is less efficient than above (which is already not efficient) because reallocation will occurs for every data instead of every structure element. Going further, you should parse first the structure to determine how many elements it contains, and then fill up your vector as you did previously. Use `numel` in a `for` statement. – jlandercy Jan 03 '14 at 05:31
  • The solution provided by thewaywewalk is elegant, efficient and robust. It simply use identity lambda function that is applied to each element of the container. My advise is: you should mark it as solution to your question. – jlandercy Jan 03 '14 at 07:18
0

You can padding each cell with zeros, and align the lengths to the longest cell vector. It is done in a loop by iterating each cell vector.

user3054997
  • 125
  • 3
  • 10
0

This depends on whether the vectors in c are row or column vectors. But usually the fastest and most compact ways are:

c={[1 2 3], [4 5 6 7 8], [9 10]}
cell2mat(c)
cat(2, c{:})

or

c={[1 2 3]', [4 5 6 7 8]', [9 10]'}
% cell2mat(c) % Doesn't work.
cat(1, c{:})

so personally, I prefer cat.

Michael Repucci
  • 1,633
  • 2
  • 19
  • 35
0

In Matlab; without loops:

  1. If the cell array contains column vectors and you want to arrange them into one big column vector:

    result = vertcat(c{:}); %// vertically concat all vectors
    

    Example:

    >> c = {[1;2], [1;2;3]};
    >> result = vertcat(c{:})
    result =
         1
         2
         1
         2
         3
    
  2. If the cell array contains row vectors, you can arrange them as rows of a matrix, filling non-existent values with NaN (or any other value):

    M = max(cellfun(@numel, c)); %// max length of vectors
    c2 = cellfun(@(row)[row NaN(1,M-numel(row))], c, 'uni', 0); %// fill with NaN
    result = vertcat(c2{:}); %// concat all equal-size row vectors into a matrix
    

    Example:

    >> c = {[1 2], [1 2 3]};
    >> M = max(cellfun(@numel, c));
    >> c2 = cellfun(@(row)[row NaN(1,M-numel(row))], c, 'uni', 0);
    >> result = vertcat(c2{:})
    result =
         1     2   NaN
         1     2     3
    
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147