A (possibly compact) way to find (1) unique rows, when rows have switched elements, (2) rows with switched elements, and (3) indices of rows with switched elements
이전 댓글 표시
I have a 2-column matrix and I would need to find the following quantites, possibly in a compact way:
- unique rows, even when the two elements of rows are switched among each other ("u"). With "switched among each other" I mean, for example, that the row ''1 2" is equivalent to the row "2 1".
- rows with switched elements ("s").
- indices of rows with switched elements ("is").
Example:
% input: a 2-column matrix
a = [1 2
4 5
5 1
2 1
1 2
5 2
5 1
1 5
2 9
5 1]
% desired output (1): unique rows
u =
1 2
1 5
2 9
4 5
5 2
% desired output (2): rows with switched elements
s =
1 2 % equivalent to "2 1"
1 5 % equivalent to "5 1"
% desired output (3a): indices in matrix "a" indicating the row "1 2" (equivalent to "2 1")
is(1) =
1
4
5
% desired output (3b): indices in matrix "a" indicating the row "1 5" (equivalent to "5 1")
is(2) =
3
7
8
10
Any suggestions?
Obviously, when the elements of the rows are switched, the unique function does not provide such features (right?):
u = unique(a,'rows')
1 2
1 5
2 1
2 9
4 5
5 1
5 2
댓글 수: 4
The order of wanted output looks strange:
1 2
1 5
2 9
4 5
5 2
Would this order work also:
a = [1 2
4 5
5 1
2 1
1 2
5 2
5 1
1 5
2 9
5 1];
as = sort(a, 2);
[~, ias] = unique(as, 'rows', 'sorted');
as(ias, :)
% or:
[~, ias] = unique(as, 'rows', 'stable');
a(ias, :)
Wondering about the output, the rest of the wanted indices are not clear also to me.
Jan
2022년 6월 10일
Okay. Thanks for your explanation. It is still unclear to me, why you pick [1 5] and not [5, 1] as result, when the input contains [5, 1; 1, 5], and why [2, 9] appears before [4, 5] in the output.
But this is obviously exactly, what you need. The demands are such specific and some details not mentioned, that I assume no one but you needs this piece of code.
Sim
2022년 6월 13일
채택된 답변
추가 답변 (2개)
Mitch Lautigar
2022년 6월 9일
0 개 추천
There isn't a compact way to do this. You will need to build a for loop for each of the conditions you are attempting to do. I've put some code below to help you get started.
%unique rows
a1 = a; %built in for you to compare after the coding is done.
a_temp = []; %this is going to be the "stack" array.
for ii = 1:length(a)
a_temp = [a_temp;sort(a(ii,:))]; Sort all values for each individual row
ends
unique_a = unique(a_temp,'rows'); %gives you the unique rows
%duplicate rows & indices
[x,y] = size(unique_a) %I use this here because this is safer than using length here.
for ii = 1:x %use this for loop to index through the unique array
for jj = 1:length(a_temp) %use this for loop to index through the a_temp array
%the goal for you to do here is to index through the a_temp array finding where the arrays are equivalent.
%the 2 hints i'll give you: You can convert each array to string and use strcmpi(), or take each row from the unique array
%and compare it against all the rows of the a_temp array
end
end
댓글 수: 7
Sim
2022년 6월 9일
Mitch Lautigar
2022년 6월 9일
Yes. I've set up the for loop to do numerical indexing, but changing them to strings would arguably be simpler. I just don't know if you are doing this for work, or for school and kept my code ambiguous for the second for loop.
Mitch Lautigar
2022년 6월 9일
Also, if my code got you towhere you need to be, please accept my code vs. accepting your own code.
Mitch Lautigar
2022년 6월 9일
I purposefully did not give a full solution. MATLAB answers is meant to guide people to the answer as we don't wish to just give out answer to possible students. I Did the first for loop (unique rows) for you and then set you up to handle the other two tasks. You just needed to take my code and play with it. Breakpoints are your friend.
Jan
2022년 6월 9일
Replace
a_temp = []; %this is going to be the "stack" array.
for ii = 1:length(a)
a_temp = [a_temp;sort(a(ii,:))]; Sort all values for each individual row
end
by
a_temp = sort(a, 2)
Sim
2022년 6월 10일
Although I'm still not sure about the order of outputs, this is how I would solve the problem:
n = size(a, 1);
ua = zeros(size(a));
k = 0;
found = false(n, 1);
match = false(n, 1);
is1 = cell(n, 1);
is2 = cell(n, 1);
s = zeros(size(a));
is = 0;
for ia = 1:n
if ~found(ia)
a1 = a(ia, 1);
a2 = a(ia, 2);
match(:) = false;
switched = false;
for ib = ia + 1:n
if a(ib, 1) == a1 && a(ib, 2) == a2
match(ib) = true;
elseif a(ib, 2) == a1 && a(ib, 1) == a2
match(ib) = true;
if ~switched % [EDITED] collect s: First switched row
is = is + 1;
s(is, 1) = a2;
s(is, 2) = a1;
end
switched = true;
end
end
k = k + 1;
if any(match) % Row exists twice
match(ia) = true; % EDITED: ia added
if switched
ua(k, 1) = min(a1, a2);
ua(k, 2) = max(a1, a2);
is2{k} = find(match)];
else
ua(k, :) = a(ia, :);
is1{k} = find(match);
end
found = found | match; % Already checked, to be ignored later
else % Unique row:
ua(k, 1) = a1;
ua(k, 2) = a2;
end
end
end
ua = ua(1:k, :); % Crop unused output
s = s(1:is, :); % Crop unused output
% Maybe: is1 = is1(~cellfun('isempty', is1));
% Maybe: is2 = is2(~cellfun('isempty', is2));
I assume, this is not a perfect solution for you, but maybe a method to create an altertative approach which is possibly faster.
댓글 수: 3
카테고리
도움말 센터 및 File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!