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
    8 visualizaciones (últimos 30 días)
  
       Mostrar comentarios más antiguos
    
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 comentarios
  Jan
      
      
 el 10 de Jun. de 2022
				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.
Más respuestas (2)
  Mitch Lautigar
      
 el 9 de Jun. de 2022
        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 comentarios
  Jan
      
      
 el 9 de Jun. de 2022
				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)
  Jan
      
      
 el 10 de Jun. de 2022
        
      Editada: Jan
      
      
 el 13 de Jun. de 2022
  
      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 comentarios
Ver también
Categorías
				Más información sobre Matrix Indexing en Help Center y File Exchange.
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!


