1

I have a two arrays within a <1x2 cell>. I want to permute those arrays. Of course, I could use a loop to permute each one, but is there any way to do that task at once, without using loops?

Example:

>> whos('M')
  Name      Size            Bytes  Class    Attributes

  M         1x2              9624  cell    

>> permute(M,p_matrix)

This does not permute the contents of the two arrays within M.

I could use something like:

>> for k=1:size(M,2), M{k} = permute(M{k},p_matrix); end

but I'd prefer not to use loops.

Thanks.

16
  • 1
    Do those two arrays have the same number of dimensions ndims(M{1}) == ndims(M{2})? If so, do they also have the same sizes? Are those arrays both numeric? Commented Nov 11, 2014 at 11:34
  • 1
    You don't want to use loops on a 1-by-2 array??? Why not? Commented Nov 11, 2014 at 11:45
  • @Divakar Yes, they have the same dimensions and they are numeric. The cell array usually is 1x2, but it could be 1xN, where N could be a vastly large number. Commented Nov 11, 2014 at 12:07
  • @Dan The cell array usually is 1x2, yes, but it could be 1xN, where N could be a vastly large number. Commented Nov 11, 2014 at 12:08
  • 1
    @baister In addition to what Divakar is probably about to post as an answer: why do you use a cell array if all (N-dimensional) arrays have the same sizes? You could use an N+1-dimensional array, which is more efficient than cell arrays Commented Nov 11, 2014 at 12:40

1 Answer 1

0

This seems to work -

num_cells = numel(M) %// Number of cells in input cell array
size_cell = size(M{1}) %// Get sizes

%// Get size of the numeric array that will hold all of the data from the 
%// input cell array with the second dimension representing the index of 
%// each cell from the input cell array
size_num_arr = [size_cell(1) num_cells size_cell(2:end)] 

%// Dimensions array for permuting with the numeric array holding all data
perm_dim = [1 3:numel(size_cell)+1 2]

%// Store data from input M into a vertically concatenated numeric array
num_array = vertcat(M{:})

%// Reshape and permute the numeric array such that the index to be used
%// for indexing data from different cells ends up as the final dimension
num_array = permute(reshape(num_array,size_num_arr),perm_dim)
num_array = permute(num_array,[p_matrix numel(size_cell)+1])

%// Save the numeric array as a cell array with each block from
%// thus obtained numeric array from its first to the second last dimension 
%// forming each cell
size_num_arr2 = size(num_array)
size_num_arr2c = num2cell(size_num_arr2(1:end-1))
M = squeeze(mat2cell(num_array,size_num_arr2c{:},ones(1,num_cells)))

Some quick tests show that mat2cell would prove to be the bottleneck, so if you don't mind indexing into the intermediate numeric array variable num_array and use it's last dimension for an equivalent indexing into M, then this approach could be useful.

Now, another approach if you would like to preserve the cell format would be with arrayfun, assuming each cell of M to be a 4D numeric array -

M = arrayfun(@(x) num_array(:,:,:,:,x),1:N,'Uniform',0)

This seems to perform much better than with mat2cell in terms of performance.

Please note that arrayfun isn't a vectorized solution as most certainly it uses loops behind-the-scenes and seems like mat2cell is using for loops inside its source code, so please do keep all these issues in mind.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.