Search code examples
matlabsearchkeyindices

Search parallel rows of a structures for common items in matlab


I've stored (row,col,val) information of

 key1:         (1,1) (1,2) (1,3) (4,2) (3,4)  
 attribute1:    2      3    4      2     5  

as follows:

 Structure A1:
 key row1:      1  1  1  4  3 
 key col1:      1  2  3  2  4
 attribute1:    2  3  4  2  5

Similarly, for structure A2

 Structure A2:
 key row2:      2  2  1  3 
 key col2:      1  2  3  4
 attribute2:    1  0  1  5 

Now, I'd like to be able to search for common entries in both row and column key items between structure A1 and A2 simultaneously. That is conceptually find [common_item, index]=intersect([row2,col2],[row1,col1]). I'd like the final result is insensitive to the order of row and col. So, in my example (1,2) key value is equal to (2,1) value. Then, the attribute value of common entries should be added together. The intended result is

 Structure Result:     //it recognizes (1,2) and(2,1) are the same.
 key row:      2  1  3 
 key col:      1  3  4
 attribute:    4  5  10 

How should I proceed to search for common entries and do some operation ? ismember function can search for common item just in one row and if there are multiple occurrence, it just count the first. In addition, as I said, I want it to be order insensitive in key values.

Thanks for any help.


Solution

  • first use sort to achieve row-col order insensitivity, next use unique to handle row-col duplicates within each structure, and finally use ismember (with 'rows') to find common keys between the structures. note that I added an inner duplication to each structure to show the second stage effect:

    % struct1
    row1 = [1  1  1  2  4  3];
    col1 = [1  2  3  1  2  4];
    att1 = [2  3  4  6  2  5];
    % struct2
    row2 = [2  2  1  3  3];
    col2 = [1  2  3  1  4];
    att2 = [1  0  1  1  5];
    % sort in 2nd dimension to get row-column indexes insensitive for order
    idx1 = sort([row1(:) col1(:)],2);
    idx2 = sort([row2(:) col2(:)],2);
    % search for duplicates inside each struct
    [idx1,~,bins1] = unique(idx1,'rows','stable');
    att1 = accumarray(bins1,att1);
    [idx2,~,bins2] = unique(idx2,'rows','stable');
    att2 = accumarray(bins2,att2);
    % search common entries
    common1 = ismember(idx1,idx2,'rows');
    row = idx1(common1,1);
    col = idx1(common1,2);
    common2 = ismember(idx2,[row col],'rows');
    % add common values
    att = att1(common1) + att2(common2);
    Result.row = row';
    Result.col = col';
    Result.attribute = att';
    disp(Result)
    

    and you get:

    Result = 
              row: [1 1 3]
              col: [2 3 4]
        attribute: [10 6 10]