MATLAB Answers

0

For every matrix row find rows within the same matrix that have more than one common element in same index below the row

Asked by Pseudoscientist on 27 Apr 2019
Latest activity Edited by Pseudoscientist on 27 Apr 2019
Let's say I have matrix A, every row contains three values and for every row of the matrix A need to find other rows that have more than one common element in same index below the present row. For example for row i, we are interested in rows i+1:end. Matrix A is sorted. If for a row there's no rows found that fulfil this condition the result cell should have value 0 in that row number.
A = [
1 2 3
1 4 5
3 4 5
1 2 4
1 2 5
2 4 5]
Result =
4,5
3,5,6
6
5
0
I'm looknig for a fast way to do that, the fastest I've done takes 90 minutes with 230k rows

  3 Comments

That output is not possible, as numeric arrays cannot be "ragged". You would either need a rectangular numeric array with padding, or else a cell array as output.
Why is the output for the second row not 3,5,6, since [1 4 5] matches [1 2 5] at both 1 and 5 ? Why is the output for the 4th row not 5, since [1 2 4] matches [1 2 5] at both 1 and 2 ?
It looks to me as if you have a secret additional condition, that once a row below has matched, it is removed from further consideration.

Sign in to comment.

Tags

2 Answers

Answer by the cyclist
on 27 Apr 2019
 Accepted Answer

Here is a start at a solution for you.
A = [
1 2 3
1 4 5
3 4 5
1 2 4
1 2 5
2 4 5];
for i = 1:size(A,1)-1
r{i} = find(sum(A(i,:)==A(i+1:end,:),2)>=2)+i;
end
Some notes:
  • It stores the results in a cell array, r, to avoid the ragged-edge issue that Walter points out.
  • It stores an empty set, rather than a zero, if no matching rows are found.
  • It finds more rows than you've pointed out, for the reason that Walter mentioned in his second comment above.
All of these issues are easily resolved, but you need to make a better specification of your rules and output formatting.

  0 Comments

Sign in to comment.


Answer by Walter Roberson
on 27 Apr 2019

t1 = tril(A(:,1) == A(:,1).', -1);
t2 = tril(A(:,2) == A(:,2).', -1);
t3 = tril(A(:,3) == A(:,3).', -1);
mask = t1+t2+t3 > 1;
Then extract the positions from this. For example,
sort( mask .* (1:size(t1,1).', 'descend')
would give an array in which the columns contain the indices per row, zero padded at the end. Or you could
arrayfun(@(IDX) find(mask(:,IDX)), 1:size(mask,2), 'uniform', 0)

  0 Comments

Sign in to comment.