Elliot Gorokhovsky
Elliot Gorokhovsky

Reputation: 3762

MATLAB/OCTAVE Extracting elements from different sized vectors in a cell array

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?

Upvotes: 4

Views: 1601

Answers (5)

Robert Seifert
Robert Seifert

Reputation: 25232

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

Upvotes: 3

Luis Mendo
Luis Mendo

Reputation: 112659

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
    

Upvotes: 0

Michael Repucci
Michael Repucci

Reputation: 1663

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.

Upvotes: 0

jlandercy
jlandercy

Reputation: 11002

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.

Upvotes: 2

user3054997
user3054997

Reputation: 125

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.

Upvotes: 0

Related Questions