1

I have two cell arrays of different sizes and want to compare the cells in the first column of cellarray1 with the cells of the first column of cellarray2. If two cells are equal, take the information in the succeeding columns in that row in cellarray2 [could be a string, an int], and put it in cellarray1. What I need really is to know how to expand cellarray1 this flexibly.

The first columns of the two arrays are strings, Po001, Po002 etc... Cellarray1 will have two copies of each string, Po001, Po001, Po002, Po002 etc.
It's just that, I need to match the two arrays, if they match, I add the information in the other columns of cellarray2 which should be general, that is, the second column contains strings with two values e.g. Object1, Object2. The third column contains a 1 or 2. It just that I don't know how to expand rows of cellarrays with new cells, which after a whole for loop results in N new columns in cellarray1.

for ii = 1:length(cellarray2(:,1))
     for jj = 1:length(cellarray1(:,1))
         if strcmp(cellarray2{ii,1}, cellarray1{jj,1})
            % This seems to give the results I want but I 
            % dont know how to update the original cellarray1 
            % with this new row 
            [cellarray1(ii,1:end), cellarray2(jj,1:end)]
         end
     end
end

If this can be done it would be really good. Ideally, I would like to input the information from cellarray2, just after the first column of cellarray1. Like, create one column in cellarray1, for each column of cellarray2, and then input that information in cellarray1 if of course the comparison is true.

Best regards,
Granit

augusti
  • 401
  • 3
  • 6
  • 16
  • is everything in cellarray2 for sure in cellarray1? – Finn Sep 08 '16 at 12:37
  • Could you give an example of what (parts) of the cellarray1 and cellarray2 look like? And, also if possible, an example of how the ouput would look like. – NLindros Sep 08 '16 at 12:46
  • Thanx for your engagement. I've added the information you asked for. As for the output, it will just be a cellarray, a merging of cellarray1 and cellarray2, with the rows of cellarray2 merged with the correct row of cellarray1. – augusti Sep 08 '16 at 14:05

2 Answers2

2

You can create a vector of indexes to indicate which rows from cellarray1(:,1) match with cellarray2(:,1) using cellfun , find and strcmp

% Find the first location of match from cellarray1 in cellarray2
locIdx = cellfun(@(x)find(strcmp(x,cellarray2(:,1)),1),cellarray1(:,1)); 

Now you can copy columns from cellarray2 to cellarray1 like:

cellarray1(:,2:end) = cellarray2(locIdx,2:end);  
% I used 2:end assuming you want to copy only the non key columns

Or if you want to append the columns into cellarray1:

width2 = size(cellarray2,2);
cellarray1(:,end+1:end+width2-1) = cellarray2(locIdx,2:end);
Some Guy
  • 1,787
  • 11
  • 15
  • Excellent. Using cellarray1(:,2:end) = cellarray2(locIdx,2:end) led to a dimension mismatch. But the last stuff you wrote did the job (I seem not to be able to upvote)! – augusti Sep 09 '16 at 08:20
0

The answer from @Some Guy overrides the values from cellarray1 with the values from cellarray2. i feel like you were looking for a solution where you would add them at the end of the array so in case i was right here would be a solution:

%please always add data examples to your posts
cellarray1={'A' 1;'B' 2;'C' 3;'D' 4;'E' 5};
cellarray2={'A' 'X'; 'D' 'Y';'E' 'Z'};

%there is no width() so you have to do it like this or with size()
width1=length(cellarray1(1,:));
width2=length(cellarray2(1,:));

for ii = 1:length(cellarray2(:,1))
     for jj = 1:length(cellarray1(:,1))
         %you got the ii and jj mixed up here
         if strcmp(cellarray2{ii,1}, cellarray1{jj,1})
           %either you overwrite everything with this 
           %cellarray1(ii,1:width1+width2-1) = [cellarray1(ii,:) cellarray2(jj,2:end)];
           %or you just add them at the end on cellarray1 with this
           cellarray1(jj,width1+1:width1+width2-1) = cellarray2(ii,2:end);
         end
     end
end

please note that when the if case is true for the first time cellarray1 will change its size from (X,width1) to (X,width1+width2-1). Also i feel like performance is not an issue here, but if this cellarray1 and cellarray2 are really big or this function should be called a lot, you should vectorize both for loops.

Finn
  • 2,333
  • 1
  • 10
  • 21
  • I misunderstood the question in the beginning and have updated my answer accordingly, if appending vs overwriting is a concern I have added that as well. Please upvote if you think mine is a good way to get this done. – Some Guy Sep 08 '16 at 15:24
  • nice! in that case you should take his solution, as that would be the vectorization i mentioned in the end of mine – Finn Sep 08 '16 at 15:34
  • @Granit you should know though that `cellfun` is not vectorization, it's just a fancy loop (but can be slower than a simple `for`). Try to benchmark (using `timeit`) the solutions to see what is really faster. – EBH Sep 08 '16 at 20:57
  • I havent really looked into vectorization. I naturally think in for loops. But will definitely look it. And thanx @EBH for further information. – augusti Sep 09 '16 at 08:22
  • The time for @SomeGuy 's solution is 0.0161 while with the for loop solution given by Finn is 0.0487. Its not a huge dataset. – augusti Sep 09 '16 at 08:47
  • @Granit Well, that's great, and it's mostly because Finn used nested loop, while @SomeGuy used only one `cellfun`. – EBH Sep 09 '16 at 08:59
  • also he uses the loop only to find the indices, but the assining is vectorized. i believe you could vectorize the `strcmp` part too (with `ismember` or something), but it seems the dataset does not require further optimization – Finn Sep 09 '16 at 09:04