61 views (last 30 days)

Show older comments

I have two structures in a for loop with i = 1:n

A(i).a

B(i).b

For each loop i, the field a of structure A contains a double array with r(i) rows and 1 column, and the field b of structure B contains a double array with r(i) rows and m columns. In other words, the number of rows of the double array in the field of each structure changes with i and it is the same for both structures and equal to r(i). Also, the number of columns in field a of structure A is fixed and equal to 1, and the number of columns in field b of structure B is fixed and equal to m.

For each loop i, I want to find out the column index for each row of the double array contained in field b of structure B of the element which has a value equal to the value of the element on the same row of the double array contained in field a of structure A. For each loop i, the result should be a double array with 1 column and a number of rows equal to the number of rows of the double array in each field. I want to store the result in a structure R(i).r.

I tried the following, but it only works when the number of rows of the double arrays is equal to 1. When the number of rows of the double arrays is >1, I get all kind of wrong numbers!

R(i).r = find(B(i).b(:,:) == A(i).a(:));

Thank you very much!

Stephen Cobeldick
on 16 May 2019

" I get some meaningless numbers."

"which is meaningless considering that the maximum number of columns of the double array..."

They are certainly not meaningless. As its documentation clearly states, with only one output argument find returns the linear indices (not column or row indices as you seem to assume).

"...the value A(40).a = 16.8967..."

Checking for equality of such values is very likely to fail due to floating point error issues. You should be using ismembertol or comparing the absolute difference against a tolerance.

As an aside, what is the point in using structure with just one field? Why not use a simpler container (e.g. a cell array)?

Stephen Cobeldick
on 16 May 2019

Edited: Stephen Cobeldick
on 16 May 2019

Note that these methods assume that there is exactly one match per row. If this is not the case, then there is no way to distinguish how many matches each row has (unless you also store the row indices, or use linear indices, or find the closest values (e.g. min) rather than trying to find matching values, etc.).

Method One: difference and find:

for k = 1:81

% Difference of floating point numbers:

mat = bsxfun(@minus,A(k).a,B(k).b);

idx = abs(mat)<1e-5;

% Translate & get column&row indices:

[idc,idr] = find(idx.');

% Store column indices:

R(k).r = idc;

end

Checking:

>> A(45).a

ans =

12.021

12.355

12.371

13.352

2.696

13.119

13.743

>> B(45).b

ans =

Columns 1 through 10

2.0648 -0.76368 0.11314 2.3052 2.8992 3.5073 3.7053 6.2226 5.7135 4.8649

1.1811 1.1602 2.54 5.1009 6.8569 8.9056 8.6338 8.6547 9.052 7.9753

1.525 -0.49692 -0.068542 0.89102 2.1247 3.1357 3.4955 5.0548 4.8492 4.2495

3.3975 3.7438 9.1755 11.621 11.361 13.352 12.551 15.494 14.953 13.374

1.5649 1.7044 3.1453 3.7496 4.2454 4.2144 4.5398 4.7567 3.5637 2.4171

2.7443 1.2311 3.206 5.9502 6.4119 8.3098 13.119 14.773 18.197 17.504

1.8486 2.5462 2.4416 5.7551 8.0223 10.952 13.743 11.441 10.185 13.115

Columns 11 through 20

5.2326 7.0994 8.2874 10.607 11.116 11.215 11.102 12.021 12.742 12.261

7.3482 7.6304 6.9928 9.2296 8.7175 9.5746 9.2192 9.8882 10.954 10.902

3.4955 5.8773 6.854 7.6079 6.4599 9.7841 10.761 12.371 13.451 10.572

12.854 12.681 15.646 18.697 16.1 16.555 17.875 16.187 13.568 11.296

0.092961 -0.092963 2.0452 2.4636 1.7663 4.6948 1.7818 4.5863 5.6554 4.0905

18.851 20.518 21.634 21.211 19.441 21.07 22.262 23.634 25.507 23.788

13.812 11.615 15.068 18.591 19.114 22.707 21.904 25.044 26.822 25.183

Columns 21 through 22

13.067 12.374

12.355 12.93

11.618 10.966

10.863 6.5787

1.9213 2.696

26.661 24.481

24.695 20.893

>> R(45).r

ans =

18

21

18

6

22

7

7

>>

Method Two: ismembertol and ind2sub:

for k = 45

% Match floating point values:

idx = ismembertol(B(k).b,A(k).a);

% Translate & get column&row indices:

[idc,idr] = ind2sub(size(B(k).b.'),find(idx.'));

% Store column indices:

S(k).r = idc;

end

Checking:

>> S(45).r

ans =

18

21

18

6

22

7

7

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!