Get notified about new tutorials
RECEIVE NEW TUTORIALS

First 15 Minutes Free

310 sessions given

since Jul 09, 2014

since Jul 09, 2014

Likelihood of Reply:
95%

Response Time:
within an hour

Ray Phan

Jul 09, 2015

<p>Assuming that each cell has two rows and a variable amount of columns where the first row is the ID and the second row is an attribute, I'd consolidate all of the cells into a single 2D matrix and use <a href="http://www.mathworks.com/help/matlab/ref/accumarray.html" rel="nofollow"><code>accumarray</code></a>. <code>accumarray</code> is very suitable here because you want to group values that belong to the same ID together and apply a function to it. In our case, our function will simply place the values in a cell array and we'll make sure that the values are sorted because the values that are grouped by <code>accumarray</code> per ID come into the function in random order. </p>
<p>Use <a href="http://www.mathworks.com/help/matlab/ref/cell2mat.html" rel="nofollow"><code>cell2mat</code></a> to convert the cells into a 2D matrix, transpose it so that it's compatible for <code>accumarray</code>, and use it. One thing I'll need to note is that should any IDs be missing, <code>accumarray</code> will make this slot empty. What I meant by missing is that in your example, the ID 4 is missing as there is a gap between 3 and 5 and also the ID 6 between 5 and 7 (I added the example in your comment to me). Because the largest ID in your data is 7, <code>accumarray</code> works by assigning outputs from ID 1 up to ID 7 in increments of 1. The last thing we would need to tackle is to eliminate any empty cells from the output of <code>accumarray</code> to complete the grouping.</p>
<p>BTW, I'm going to assume that your cell array consists of a <strong>single</strong> row of cells like your example.... so:</p>
<pre><code>%// Setup
A{1,1}=[1 2;2 4];
A{1,2}=[2 3 5;8 5 6];
A{1,3}=[7;8];
%// Convert row of cell arrays to a single 2D matrix, then transpose for accumarray
B = cell2mat(A).';
%// Group IDs together and ensure they're sorted
out = accumarray(B(:,1), B(:,2), [], @(x) {sort(x)});
%// Add a column of IDs and concatenate with the previous output
IDs = num2cell((1:numel(out)).');
out = [IDs out];
%// Any cells from the grouping that are empty, eliminate
ind = cellfun(@isempty, out(:,2));
out(ind,:) = [];
</code></pre>
<p>We get:</p>
<pre><code>out =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> celldisp(out(2,:))
ans{1} =
2
ans{2} =
4
8
</code></pre>
<hr>
<p>If you'd like this done on a 2D cell array, where each row of this cell array represents a separate instance of the same problem, one suggestion I have is to perhaps loop over each row. Something like this, given your example in the comments:</p>
<pre><code>%// Setup
A{1,1}=[1 2;2 4];
A{1,2}=[2 3 5;8 5 6];
A{1,3}=[7;8];
A{2,1}=[1 2;2 4];
A{2,2}=[1;7];
%// Make a cell array that will contain the output per row
out = cell(size(A,1),1);
for idx = 1 : size(A,1)
%// Convert row of cell arrays to a single 2D matrix, then transpose for accumarray
B = cell2mat(A(idx,:)).';
%// Group IDs together and ensure they're sorted
out{idx} = accumarray(B(:,1), B(:,2), [], @(x) {sort(x)});
%// Add a column of IDs and concatenate with the previous output
IDs = num2cell((1:numel(out{idx})).');
out{idx} = [IDs out{idx}];
%// Any cells from the grouping that are empty, eliminate
ind = cellfun(@isempty, out{idx}(:,2));
out{idx}(ind,:) = [];
end
</code></pre>
<p>We get:</p>
<pre><code>>> out{1}
ans =
[1] [ 2]
[2] [2x1 double]
[3] [ 5]
[5] [ 6]
[7] [ 8]
>> out{2}
ans =
[1] [2x1 double]
[2] [ 4]
>> celldisp(out{1}(2,:))
ans{1} =
2
ans{2} =
4
8
>> celldisp(out{2}(1,:))
ans{1} =
1
ans{2} =
2
7
</code></pre>
<p>This tip was originally posted on <a href="http://stackoverflow.com/questions/31217436/Merging%20elements%20of%20different%20cells/31217533">Stack Overflow</a>.</p>