问题
Suppose I have a cell
A = {[3,0], [2,1]}
and a cell array
B = {[4,-1],[3,0];
[-1,4],[-3,5];
[3,0],[2,1];
[2,1],[-1,4]}.
I want to find the indices where both the first or second entry in A
shows up in B
excluding the row in B
where both entries of A
show up.
In this example I should get something like [1 4]
for the rows in B
. I've been trying to figure this out using cellfun
and cell2mat
but keep stumbling.
回答1:
I would approach this problem by converting my cell arrays to numeric arrays of appropriate dimensions, and then use ismember
.
The following example illustrates how this method works on the example cell arrays in the question:
%# Build the example cell arrays
A = {[3,0], [2,1]};
B = {[4,-1],[3,0];
[-1,4],[-3,5];
[3,0],[2,1];
[3,0],[3,0];
[2,1],[-1,4]};
%# Get the number of elements in A, and the length of the first element
K = size(A, 2);
J = length(A{1, 1});
%# Convert cell arrays to usefully shaped numerical matrices
ANumVec = cell2mat(A);
ANum = reshape(ANumVec, K, J)';
BNum = cell2mat(B);
%# Find matches of 1*2 vectors in ANum in sets of two columns of BNum
I1 = ismember(BNum(:, 1:J), ANum, 'rows');
I2 = ismember(BNum(:, J+1:end), ANum, 'rows');
I3 = ismember(BNum, ANumVec, 'rows');
%# Find all indices where there was exactly 1 match (ie omit cases of no matches and cases of 2 matches)
MainIndex = I1 + I2;
MainIndex(I3) = 0;
Soln = find(MainIndex > 0);
Some points:
1) This method finds the indices of all rows in B
where an element of A
lies in the first or second column of B
, excluding the situation where A
corresponds exactly to a row of B
.
2) This method will fail if there are multiple rows in A
. However, it is robust to A
being a cell array of size 1*N, where N denotes some arbitrary number of 1*2 numeric vectors. Thus the single row limitation can be circumvented by first reshaping A
to a 1*N cell array.
3) Equivalence is tested using the logical operator ==
. This can be dangerous with floating point numbers unless you have reason to believe a priori that your inputs will not exhibit any floating point error.
4) I can't shake the feeling that there is a much more efficient way to solve this problem, but that I'm not seeing it at the moment. :-)
回答2:
quick and dirty:
C=zeros(size(B));
for i=1:size(C,1);
for j=1:size(C,2);
for k=1:length(A);
C(i,j)=C(i,j)+isequal(B{i,j},A{k}); % Does element k of A match?
end;
end;
end;
find(sum(C')==1) % Sums the rows and finds the rows with only one match
来源:https://stackoverflow.com/questions/14431860/check-if-entries-in-a-cell-are-in-a-cell-arrary