How to stop a for loop after comparing one value from an array with another value from another array?

c_year = [0 2 3 4 6 7 8 10];
l_year = [1 5 9];
count = 1188;
statement = true ;
for j = 1:length(l_year)
for i =1:length(c_year)
if c_year(i) >l_year(j)
count = count - j;
break
end
end
end
I want the loop to stop when the value in c_year is bigger than the value in l_year (e.g. stop when c_year value is 2 and l_year value is 1 and then take away 1 from count, or when c_year value is 6 and l_year value is 5 and take away 2 from count (because it is the 2nd value in l_year) or compare 10 and 9 and take away 3 from counter, I assume you get the idea).
Any suggestions how this can be done?
Also, sorry for the bad explanation, but I could not find a better way to explain the problem. Hope it is clear enough.

13 Comments

This is only a very short bit of my code. In summary, I cannot use
break
to terminate both loops as they contain further code which needs to be executed.
How about reducing the nested loops?
c_year = [0 2 3 4 6 7 8 10];
l_year = [1 5 9];
count = 1188;
for j = 1:length(l_year)
if find(c_year > l_year(j),1)
count = count - j;
break; % stop the loop
end
end
What do you mean 'they contain further code which needs to be executed'? The point of stopping a loop is not to execute further code. What exactly do you want to achieve?
Or do you need something like continue?
@Atsushi Ueno this works, but will it work for comparing value 6 in c_year and value 2 in l_year and subtract 2 from count?
> but will it work for comparing value 6 in c_year and value 2 in l_year and subtract 2 from count?
Yes it does, by removing the break sentence. Would you really want to stop the for loop? You might need continue as @Rik told you.
c_year = [0 2 3 4 6 7 8 10]; l_year = [1 5 9];
count = 1188;
for j = 1:length(l_year)
if find(c_year > l_year(j),1)
count = count - j;
sprintf('j = %d, count - j = %d', j, count)
end
end
ans = 'j = 1, count - j = 1187'
ans = 'j = 2, count - j = 1185'
ans = 'j = 3, count - j = 1182'
@Andrei: What is the wanted output? I still do not understand, what you want to achieve.
A bold guess:
c_year = [0 2 3 4 6 7 8 10];
l_year = [1 5 9];
count = 1188;
a = (c_year > l_year.') .* (1:numel(c_year))
a = 3×8
0 2 3 4 5 6 7 8 0 0 0 0 5 6 7 8 0 0 0 0 0 0 0 8
result = count - cumsum(a(a~=0))
To give some background information, I have a variable 'data' with 2 columns of information starting from 1st Oct 1990 and another variable 'binary' with 0s and 1s. 0s for all the days in a common year and 1s for all the days in a leap year. The array c_year stands for common years (0 being 1991 and so on) and l_year for leap years (1 being 1991+1 =1992). What I have to do is create a function that displays the maximum value of 'data' and the date when it happens. And if the max value happens to be in 1997, then to calculate the date I should take away 2 from the corresponding index in 'data' because there from 1990 to 1997 there were 2 leap years. So 1997 would correspond to 6 in c_years and I want to subtract 2 from count because as I said, 2 leap years have passed, that is why I want to compare the index in c_years with the biggest value in l_years less than the index in c_years and take away the index corresponding to the condition stated above(e.g. if it is 1997, then i = 6 and j = 2 (2nd value in l_years) so count = count - j)
Hope this clarifies my question and hasn't made it more confusing.
I still do not know, what the wanted result for the data in the question is.
I want the function to output the date corresponding the maximum value in 'data'
@Andrei: Again: If the input is
c_year = [0 2 3 4 6 7 8 10];
l_year = [1 5 9];
count = 1188;
what is the wanted result for count? It is a number, isn't it?
The explanation "maximum value in 'data'" is not useful, because there is no variable called data and it is not mention, that maximum of what is wanted.
Yes, the wanted result for count is 1187 because in this case only 1 leap year has passed so count = count - 1.

Sign in to comment.

 Accepted Answer

Happy new year! What an appropriate time to answer this question... 😂
My understanding, from reading the comments, is that you want to calculate the duration in days between 2 dates, excluding leap days (the additional day in leap years). Specifically, between 1st Oct 1990 and the date corresponding to the maximum of an Mx2 matrix, data.
Presumably this is because you have some calendar data (i.e., it includes leap days) and some model which does not consider leap years, and you want to compare the 2. If so, potentially better solutions include:
  • Convert each data set matrix to a timetable with associated dates (array2timetable) and synchronize the two (synchronize with an interpolation method). See [1], [2]. Like this you can artificially add data for the leap days.
  • Remove the leap days (29th Feb) from the calandar data, see this answer and this answer. Then your count will just be your column number, i.e. 1:N. Just be aware that if you do this, most MATLAB built-in date/time functions will get confused, as "days" don't exist without leap years, only 24-hour periods exist.
  • You can continue to do it your way, calculating duration without leap days, but then you have some tricky decisions to make. Will you remove a day if you're currently in a leap year? What about if you're in a leap year either before 29 Feb or on 29 Feb? P.S. Instead of entering c_year and l_year manually, here's a neat little trick, courtesy of this answer:
isLeapYear = ~(datetime(1990:2000,2,29)==datetime(1990:2000,3,1))
isLeapYear = 1×11 logical array
0 0 1 0 0 0 1 0 0 0 1
EDIT: Code in the comments below.

2 Comments

To add some code to this, all 3 options in my reply above would start like this:
% Make random, dummy data (10000-by-2 matrix).
rng( 1, "twister" )
data = rand( 10000, 2 );
% Find the maximum data row, 'daysUntilMax', equivalent to the
% initial 'count' in your example.
[ ~, maxIdx ] = max( data, [], 'all' );
[ daysUntilMax, ~ ] = ind2sub( size(data), maxIdx );
% Convert data to a timetable.
data = array2timetable( data, ...
'StartTime', datetime(1990,10,1), 'TimeStep', caldays(1) );
Then, the following shows one way of doing option 3, which is precisely what you requested in your post.
% Count the number of leap years between the start date and date of
% the maximum. If either of these are in a leap year, that will also
% be subtracted, i.e. it is inclusive.
dataYears = year( data.Time( 1:daysUntilMax ) );
yearsBetweenDates = unique( dataYears );
isleapyear = @(yearNumbers) ~( datetime(yearNumbers,2,29) == ...
datetime(yearNumbers,3,1) );
leapYearsBetweenDates = sum( isleapyear(yearsBetweenDates) );
% Subtract number of leap years (similar but distinct from number of
% leap days) from 'daysUntilMax'. 'commonDaysUntilMax' is equivalent
% to the final 'count' in your example.
commonDaysUntilMax = daysUntilMax - leapYearsBetweenDates;

Happy New Year! I will try this and then manipulate some values in the 'data' variable, corresponding with 1st Jan and 31st Dec each year, using the following link: https://www.timeanddate.com/date/durationresult.html?d1=1&m1=10&y1=1990&d2=31&m2=12&y2=1993&ti=on So index number 1188 would be the days between 1st Oct 1990 and 31st Dec 1993 and if max value occurs at index 1188 then the output date would be 31st Dec 1993.

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2022b

Community Treasure Hunt

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

Start Hunting!