You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
Define an if statement based on on finding duplicate xy pair values between arrays.
4 views (last 30 days)
Show older comments
Hello, I have 2 arrays of different sizes which I am trying to compare for duplicates using an if statement. The condition to activate this section of the code should be if there are any duplicate xy sets in between the two arrays then do these commands. Any ideas or tips for improvement will be greatly appreciated thank you. Also I know that I switch variable names a lot and its confusing.
% test for find repeat combined vein nodes/vectors
if newVN_prime10 == vein_node_array % if any values in the 2 arrays are equal this code should activate the loop
VN_VN_threshold = ((1/2)*radii_vein); % if distance between VNs is greater than this value then point should be retained
SizeNewVN_prime10 = size(newVN_prime10, 1);
newVN_prime10x = newVN_prime10(:,1);
newVN_prime10y = newVN_prime10(:,2);
reconfig_dist10 = nan(numel(VNA_x)); % preallocation step
for j = 1:SizeofVNA
for i = 1:SizeNewVN_prime10
reconfig_dist10(j,i) = sqrt((newVN_prime10x(i)-VNA_x(j)).^2 + (newVN_prime10y(i)-VNA_y(j)).^2);
end
end
% find the points that are greater than VN_VN_threshold
i2keepVN_VN = find(min(reconfig_dist10)> VN_VN_threshold); % keeps the VN points that pass the test
inot2keepVN_VN = find(min(reconfig_dist10)< VN_VN_threshold); % keeps the VN points that fail the test
% store points greater than VN_VN_threshold
x_newVN_retained = newVN_prime10x(i2keepVN_VN);
y_newVN_retained = newVN_prime10y(i2keepVN_VN);
% store points less than VN_VN_threshold
x_notkept = newVN_prime10x;
y_notkept = newVN_prime10y;
x_notkept(i2keepVN_VN) = [];
y_notkept(i2keepVN_VN) = [];
newVN_retained = [x_newVN_retained, y_newVN_retained]; % store new vein nodes the pass test
VN_VectorGroupNum = inot2keepVN_VN; % VN group # needs to be kept for linking back to proper VNA point
VN_reconfig = VN_HSvectors10{VN_VectorGroupNum}; % grabs the vector group that makes up repeated combined vector
VN_HScomb10Beta = 8*(VN_reconfig./vecnorm(VN_reconfig,2,2)); % turns vector group into scaled unit vectors
SizeVN_HScomb10Beta = size(VN_HScomb10Beta,1);
VNconfig_beta = VN_HScomb10Beta(:,:) + vein_node_array(GroupList10(VN_VectorGroupNum),:); % adds reconfigured vectors to appropriate vein node chain
end % end of if statement
19 Comments
Adam Danz
on 16 Oct 2019
Edited: Adam Danz
on 16 Oct 2019
" I have 2 arrays of different sizes which I am trying to compare for duplicates using an if statement"
% Create 2 demo arrays
newVN_prime10 = 0:3:100;
vein_node_array = 1:4:100;
% Detect if any values in 2 vectors are equal
isMatch = any(ismember(newVN_prime10,vein_node_array));
% isMatch is either TRUE or FALSE, indicating whether
% there was an exact match or not.
This assumes you are looking for exact matches. So 1.00000 would not match with 1.000000000001.
If you want to look for matches considering a tolerance level use ismembertol() instead.
That's all the further I got with understanding your question/code. The code isn't intuitive nor easy to read and would require a great deal of time and energy to try to understand what it's doing. Perhaps you could explain what you'd like to happen when there are matches found between the two vectors.
Vance Blake
on 16 Oct 2019
yeah sorry there is a lot going on and i only grabbed one section of code so Ill post the whole code and relevant files if you need. The overall goal of the code is to grow vein nodes (VN) using randomnly generated hormone seeds (HS). After a series of elimination tests which you will see in the code, I calculate the vector(s) between the existing VN and their closest hormone seeds. If one vein node is closest to 2 or more hormone seeds I will calculate the combined vector in order to grow in the direction closest to both. My problem arose from 2 hormone seeds being on opposite sides of their closest vein node. In HS gen 9 the generation before, the current one (HS gen 10) I already grew the combined vector that gets closer to the hormone seeds so in order to not repeatedly calculate and plot the same vein node I needed to use the two vectors that correspond to the individual hormone seeds themselves and plot them. So the above code is designed to recognize the presence of duplicate vectors in newVN_prime10 that already exist in the vein node arrary (matrix of all existing vein nodes). Once that if statement is true the rest of the code should locate the correct vector group based on the i count (that counts the vein nodes in newVN_prime10). For example in this specific case, the duplicate vein node in newVN_prime10 is the 2nd one. That means we need to select the 2nd cell array in VN_HSvectors10 and use the vectors stored in there as the scaled unit vectors for the new vein nodes instead of their combined vector which already exists. Right now im just using inot2keepVN_VN to hold the two because I know that only 1 vector from newVN_prime fails the test, but if there were mutiple vectors that failed my code wouldnt work properly since its not evaluating the values stored under the inot2keepVN_VN handle on a 1 to 1 basis. basically I can only select and change 1 duplicate vector but I want to be able to select and change multiple duplicate vectors according to the general process shown above.
Guillaume
on 16 Oct 2019
I haven't got the time to go through the whole question right now, but I just saw this:
if newVN_prime10 == vein_node_array % if any values in the 2 arrays are equal this code should activate the loop
The comment there is wrong. The if will be true if and only if all the elements in the 2 arrays are identical.
The code above is exactly equivalent to:
if all(newVN_prime10 == vein_node_array)
And if that is what was meant and the comment is wrong, it would be better to do the all explicitly.
Code that matches the comment would be:
if any(newVN_prime10 == vein_node_array)
Also note that all of these would throw an error if the two arrays don't have compatible size.
Adam Danz
on 16 Oct 2019
Edited: Adam Danz
on 16 Oct 2019
I think the code that matches the comment "if any values in the 2 arrays are equal..." would be
if any(ismember(newVN_prime10,vein_node_array))
The difference between this and any(A==B) is that the prior does not require the equal values to also be in the same position within the vectors. The prior version also doesn't require that the vectors are the same lenght.
Examples of lines that would return TRUE under the ismember() method but would either break or return FALSE in the A==B method
any(ismember([1 2 3 4],[0 1 2 3]))
any(ismember([1 2 3], [7 6 5 4 3]))
any(ismember([1 2 3],[3 2 1]))
any(ismember([1 2 3],[1 2 3 4]))
Guillaume
on 16 Oct 2019
Yes, it's not very clear what was meant exactly by the comment, and you may be right that ismember was meant. What's clear though is that the code didn't do what the comment said at all.
Adam Danz
on 16 Oct 2019
@Vance Blake, maybe it's best if we take this step by step (unless Guillaume or others have a clearer picture).
To start, the conditional statement at the top seems to be comparing two vectors(?) to determine if there are any exactly-matching(?) values anywhere(?) within either of the vectors. Is that correct? If not, please fill in those misunderstandings. If that's correct and matches are detected, what is the next step that isn't solved? Variable types (numeric, cell of strings, tables etc) & sizes are helpful to know.
Vance Blake
on 17 Oct 2019
Edited: Vance Blake
on 17 Oct 2019
My bad the comment was what I want to happen not what is currently happening. First both newVN_prime10 and Vein_node_array contain vectors stored as Xs and Ys. My conditional statement needs to be true only when there is an xy set in newVN_prime10 that matches a xy set in vein_node_array. If so, then I use the row number of th duplicate vector in newVN_prime10 to find the vector(s) that created that particular xy set in the array under the VN_HSvectors10 handle. @Adam, Im pretty sure the solution you gave above will do that for me and Im about to try it out.
update: it worked perfectly. Now I just hope to write it so that It can handle muliptle values being sent to inot2keep so that it can work with multiple duplicates as opposed to one. Im thinking i need a loop but I was hoping there would be a more streamlined and efficient solution.
Adam Danz
on 17 Oct 2019
Just to make sure I have a clear mental image of your data,
"both newVN_prime10 and Vein_node_array contain vectors stored as Xs and Ys"
so, newVN_prime10 and Vein_node_array look something like this,
newVN_prime10 = [1 4 2 3 5];
Vein_node_array = [4 8 5 0 5];
% Or maybe they are column vectors instead of row vectors
"My conditional statement needs to be true only when there is an xy set in newVN_prime10 that matches a xy set in vein_node_array."
So would this be the only match?
newVN_prime10 = [1 4 2 3 5];
Vein_node_array = [4 8 5 0 5];
% ^
If this is also a match,
% v v
newVN_prime10 = [1 4 2 3 5];
Vein_node_array = [4 8 5 0 5];
% ^ ^
Then my ismember() suggestion is the correct method.
Vance Blake
on 17 Oct 2019
Edited: Vance Blake
on 17 Oct 2019
Ah i understand where the confusion arises from now. Both newVN_prime10 and vein_node_array contain sets of coordinates [x, y]. Here is the data. The duplicate value is the second row entry into newVN_prime10. Both of the 2nd xy set's values are the same as coordinate set 31 in the vein_node_array. Which is why i think your method of comparison is what i need.
newVN_prime10 = [-5.90017399463671 50.9213928834708
-11.5153844741317 -54.0118643677180 % matches with point below
36.1964886696682 -27.6173471167148]
vein_node_array = [0 0
-5.52181708330649 5.78874218621840
7.84112142353224 -1.58644723247378
-10.7646822498633 11.8312884082431
-4.65529407234641 -6.50601545494448
15.6405738189426 0.193592747899640
-13.8650570115201 19.2060884961968
-18.1259465641580 8.69891108501217
-5.66375396466551 -14.4421989612392
23.4400262143529 1.97363272827306
-13.4092653004590 27.1930938120914
-24.6978726202014 4.13713643977842
-6.83408006655876 -22.3561320425349
31.2394786097633 3.75367270864648
-12.9534735893979 35.1800991279859
-5.41182274943837 26.9908250722310
-32.2089399725165 1.38325422933691
-8.00440616845200 -30.2700651238307
39.0389310051736 5.53371268901990
-18.2158651875883 41.2056476231269
11.0532845058115 -8.91324792123572
33.0410083723270 -4.04084398673607
-39.7200073248316 -1.37062798110460
-9.17473227034525 -38.1839982051264
42.7850274238196 12.6024298019201
-23.4782567857786 47.2311961182679
45.2253043784516 0.461357763899033
-13.0337883752712 47.3004060195891
34.8425381348907 -11.8353606821186
-47.2310746771467 -4.12451019154612
-10.3450583722385 -46.0979312864222
42.4392051410033 20.5949517411272
-30.8376776696154 44.0944901622454
36.6440678974544 -19.6298773775012
-54.7421420294618 -6.87839240198763
-11.5153844741317 -54.0118643677180 % matches with point above
42.0933828581870 28.5874736803344
-38.3816442372168 41.4320536039566]
Adam Danz
on 17 Oct 2019
Edited: Adam Danz
on 17 Oct 2019
Ahhhhh there we go.... Mini lesson: starting with these kinds of examples will save you much time (6 hours since first comment) ;)
Now I see 1) your working with n x 2 matricies, 2) with floating decimals, and 3) the order (or number of rows) between the two matrices do not matter.
In that case I recommend you use ismembertol() which allows you to set a small tolerance level so that roundoff error does not prevent finding matches.
[isMatch, matchRow] = ismembertol(newVN_prime10, vein_node_array,0.000001, 'ByRows',true)
isMatch =
3×1 logical array
0
1 % <---- row 2 of newVN_prime10
0
matchRow =
0
36 % <--- row 36 of vein_node_array
0
NOTE: the matchRow will return the first row in vein_node_array that provides the match. If you need a list of all rows that match, we'll need to make a modification.
To return a true/false indicating whether there was a match or not,
TF = any(ismembertol(newVN_prime10, vein_node_array,0.000001, 'ByRows',true))
Vance Blake
on 17 Oct 2019
Edited: Vance Blake
on 17 Oct 2019
yeah I keep forgetting to do that cause I can see the data but you guys can't, but once we got started I realized that I should have just included the vectors from the beginning. And i will update it accordingly. Thanks for the help with that problem. Now the second part of my question has to do with if i have 2 coordinate sets in newVN_prime10 that match with sets in vein_node_array and I need to be able to change both. As is hopefully clear, the way I have written the code only works if inot2keep is sent just one value in this cause a 2 if there are multiple matches if needs to be more flexible and adaptable.
Adam Danz
on 17 Oct 2019
Edited: Adam Danz
on 17 Oct 2019
Alternatively, you can use pdist2() to compute the distance between the coordinates of each matrix and then look for distances very close to 0. This method is slower than ismembertol().
D = pdist2(newVN_prime10, vein_node_array);
[rows1,rows2] = find(D < 0.00001);
% rows1 are the row numbers of newVN_prime10 that provide a match.
% rows2 are the row numbers of vein_node_array that provide a match.
% Display the matches
newVN_prime10(rows1,:)
vein_node_array(rows2,:)
% To determine if there are any matches,
TF = ~isempty(rows1); % True if there is a match
Adam Danz
on 17 Oct 2019
There aren't any variables named "inot2keep" in your code but I do see "inot2keepVN_VN" however I don't know what this variable is since we can't run your code. Starting with line 2, we don't know what radii_vein is, for example.
"Now the second part of my question has to do with if i have 2 coordinate sets in newVN_prime10 that match with sets in vein_node_array and I need to be able to change both"
How would you like to change them? (I'll check back tomorrow, signing off for the day).
Vance Blake
on 17 Oct 2019
Edited: Vance Blake
on 17 Oct 2019
So does this
if any(ismember(newVN_prime10,vein_node_array))
end
work the same as this
if any(ismembertol(newVN_prime10,vein_node_array,0.000001))
end
cause i dont want this part of the code to activate unless there is a match or matches. Once it recognizes the matches, then I just need to know the newVN_prime10 row number of the all the potential matched coordinates in that array because im using the row numbers to find the cell array row numbers of the vectors in VN_HSvectors10 that generated the repeat set of coordinates. Right now, I can correct only one vector but if 2 numbers get reported to inot2keepVN_VN then the code cant handle it accordingly. Im doing a terrible job of explaining it but if you run the code I attached with all the data sets up to HS gen 10 and then go thru it section by section watching the variables vein_node_array, VN_HSneighborgroups10, Grouplist10, VN_HSvectors10, and newVN_prime10 you'll hoepfully see what Im talking about
edit and yes I meant inot2keepVN_VN also thanks for your help tonight and goodnight
Guillaume
on 17 Oct 2019
ismembertol is very likely to be what you need since you're dealing with floating point values that may come from different calculations. ismembertol is designed to cope with small inaccuracies resulting from floating point computations that would fail exact comparison. See for example:
>> x = 0.1+0.1+0.1 %is x equal to 0.3?
x =
0.3
>> ismember(x, 0.3) %not according to ismember, as due to floating point precision x is not exactly 0.3 (off by about 5e-17)
ans =
logical
0
>> ismembertol(x, 0.3) %but yes according to ismembertol
ans =
logical
1
Adam Danz
on 17 Oct 2019
@Vance Blake, neither of those lines would work because you're missing the "ByRows" property. Check my comment again:
You definitely want to go with ismembertol(), also explained in that link.
Vance Blake
on 17 Oct 2019
Alright I see what you guys are saying, it is important to account for roundoff error. Now I was thinking about the second problem and in order for us to be discussing efficiently I have to provide all the information needed for you to see exactly what Im seeing and therefore understand what im asking more clearly. So Im gonna take a moment to cobble all the bits of code, arrays, and variables needed to run this section properly Im gonna post it after this comment. Also I think it's better to put this problem under a separate question, so Im gonna edit this question title to just the if statement and make another question specific to the second problem. So if either of you wants to make the ismembertol solution into answer, I'll accept it so we can close this thread and not confuse anyone in the future too much. Again, thanks for all your help.
Vance Blake
on 17 Oct 2019
Accepted Answer
Adam Danz
on 17 Oct 2019
(continuing from the comment section under the question)
I recommend you use ismembertol() which allows you to set a small tolerance level so that roundoff error does not prevent finding matches.
[isMatch, matchRow] = ismembertol(newVN_prime10, vein_node_array,0.000001, 'ByRows',true)
isMatch =
3×1 logical array
0
1 % <---- row 2 of newVN_prime10
0
matchRow =
0
36 % <--- row 36 of vein_node_array
0
NOTE: the matchRow will return the first row in vein_node_array that provides the match. If you need a list of all rows that match, we'll need to make a modification (see comments under the question).
To return a true/false indicating whether there was a match or not,
TF = any(ismembertol(newVN_prime10, vein_node_array,0.000001, 'ByRows',true))
More Answers (0)
See Also
Categories
Find more on Logical in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)