简体   繁体   中英

How can I find all the cells that have the same values in a multi-dimensional array in octave / matlab

How can I find all the cells that have the same values in a multi-dimensional array?

I can get it partially to work with result=A(:,:,1)==A(:,:,2) but I'm not sure how to also include A(:,:,3) I tried result=A(:,:,1)==A(:,:,2)==A(:,:,3) but the results come back as all 0 when there should be 1 correct answer which is where the number 8 is located in the same cell on all the pages of the array. Note: this is just a test the repeating number could be found multiple times and as different numbers.

PS: I'm using octave 3.8.1 which is like matlab

See code below:

clear all, tic
%graphics_toolkit gnuplot %use this for now it's older but allows zoom
A(:,:,1)=[1 2 3; 4 5 6; 7 9 8]; A(:,:,2)=[9 1 7; 6 5 4; 7 2 8]; A(:,:,3)=[2 4 6; 8 9 1; 3 5 8] 
[i j k]=size(A)
for ii=1:k
    maxamp(ii)=max(max(A(:,:,ii)))
    Ainv(:,:,ii)=abs(A(:,:,ii)-maxamp(ii));%the extra max will get the max value of all values in array
end

%result=A(:,:,1)==A(:,:,2)==A(:,:,3)
result=A(:,:,1)==A(:,:,2)
result=double(result); %turns  logical index into double to do find
[row col page] = find(result) %gives me the col, row, page

This is the output it gives me:

>>>A =

ans(:,:,1) =

   1   2   3
   4   5   6
   7   9   8

ans(:,:,2) =

   9   1   7
   6   5   4
   7   2   8

ans(:,:,3) =

   2   4   6
   8   9   1
   3   5   8

i =  3
j =  3
k =  3
maxamp =  9
maxamp =

   9   9

maxamp =

   9   9   9

result =

   0   0   0
   0   1   0
   1   0   1

row =

   3
   2
   3

col =

   1
   2
   3

page =

   1
   1
   1

Use bsxfun ( MATLAB doc , Octave doc ) and check to see if broadcasting the first slice is equal across all slices with a call to all ( MATLAB doc , Octave doc ):

B = bsxfun(@eq, A, A(:,:,1));
result = all(B, 3);

If we're playing code golf , a one liner could be:

result = all(bsxfun(@eq, A, A(:,:,1)), 3);

The beauty of the above approach is that you can have as many slices as you want in the third dimension, other than just three.

Example

%// Your data
A(:,:,1)=[1 2 3; 4 5 6; 7 9 8]; 
A(:,:,2)=[9 1 7; 6 5 4; 7 2 8]; 
A(:,:,3)=[2 4 6; 8 9 1; 3 5 8];

B = bsxfun(@eq, A, A(:,:,1));
result = all(B, 3);

... gives us:

>> result

result =

     0     0     0
     0     0     0
     0     0     1

The above makes sense since the third row and third column for all slices is the only value where every slice shares this same value (ie 8).

这是另一种方法:计算沿第三维的差异并检测所有这些差异何时为零:

result = ~any(diff(A,[],3),3);

你可以做

result = A(:,:,1) == A(:,:,2) & A(:,:,1) == A(:,:,3);

sum the elements along the third dimension and divide it with the number of dimensions. We get back the original value if the values are the same in all dimension. Otherwise a different (eg a decimal) value. Then find the location where A and the summation are equal over the third dimension.

all( A == sum(A,3)./size(A,3),3)

ans =

0   0   0
0   0   0
0   0   1

or

You could also do

all(A==repmat(sum(A,3)./size(A,3),[1 1 size(A,3)]),3)

where repmat(sum(A,3)./size(A,3),[1 1 size(A,3)]) would highlight the implicit broadcasting of this when compared with A .

or

you skip the broadcasting altogether and just compare it with the first slice of A

A(:,:,1) == sum(A,3)./size(A,3)

Explanation

3 represents the third dimension . sum(A,3) means that we are taking the sum over the third dimension. Then we divide that sum by the number of dimensions. It's basically the average value for that position in the third dimension. If you add three values and then divide it by three then you get the original value back. For example, A(3,3,:) is [8 8 8] . (8+8+8)/3 = 8 . If you take another example, ie the value above, A(2,3,:) = [6 4 1] . Then (6+4+1)/3=3.667 . This is not equal to A(2,3,:) .

sum(A,3)./size(A,3)
ans =

   4.0000   2.3333   5.3333
   6.0000   6.3333   3.6667
   5.6667   5.3333   8.0000

Therefore, we know that the elements are not the same throughout the third dimension. This is just a trick I use to determine that. You also have to remember that sum(A,3)./size(A,3) is originally a 3x3x1 matrix that will be automatically expanded (ie broadcasted) to a 3x3x3 matrix when we do the comparison with A ( A == sum(A,3)./size(A,3) ). The result of that comparison will be a logical array with 1 for the positions that are the same throughout the third dimension.

A == sum(A,3)./size(A,3)
ans =

ans(:,:,1) =

   0   0   0
   0   0   0
   0   0   1

ans(:,:,2) =

   0   0   0
   1   0   0
   0   0   1

ans(:,:,3) =

   0   0   0
   0   0   0
   0   0   1

Then use all(....,3) to get those. The result is a 3x3x1 matrix where a 1 indicates that the value is the same in the third dimension.

all( A == sum(A,3)./size(A,3),3)
ans =

   0   0   0
   0   0   0
   0   0   1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM