Reputation: 79
Say I have a set
M = c(-1.64, 1.99, 0.79, 1.72, 1.07, 2.12, 1.98, 0.12)
I want to make a for loop that contains an if statement depending on two conditions. If there exists numbers m_1, m_2, m_3
in M
such that
-1/2 <= m_1 < m_2 < m_3 <= 10
and m_3-m_1 <= 1/2
.
Then I want the statement k = 1
to happen, otherwise I want k = 0
. My first try/instinct was this:
for (i in 1:7){
if (-0.5 <= M[i] && M[i] < M[i+1] && M[i+1] < M[i+2] && M[i+2] <= 10 && (M[i+2]-M[i]) <= 1/2) {
k = 1
} else
k = 0
}
But now I realize that if, for example, i=6
, then M[8]
is computed, which does not exist… is there any way around this?
I also think that it's not enough with one for loop like that but I need 3 nested for loops with different indexes, but that sounds like a mess.
Upvotes: 1
Views: 170
Reputation: 145775
The only items of M
that matter are the ones between your thresholds, -0.5 and 10. So we'll get rid of everything else, and sort what remains. Then we need to take the difference between elements offset by 2 and see if any of those are less than your 0.5 difference threshold:
M = c(-1.64, 1.99, 0.79, 1.72, 1.07, 2.12, 1.98, 0.12)
sub_m = sort(M[M >= -.5 & M <= 10])
any(tail(sub_m,-2) - head(sub_m,-2) <= 0.5)
# [1] TRUE
We can wrap this up in a handy function:
foo = function(M) {
sub_m = sort(M[M >= -.5 & M <= 10])
any(tail(sub_m, -2) - head(sub_m, -2) <= 0.5)
}
foo(1:10)
# [1] FALSE
foo(M)
# [1] TRUE
I'd recommend testing it on some additional cases. I've written the function to return a logical
true or false, you can use as.integer
on it if you'd prefer to have a numeric result. You could also parametrize the function to optionally input different thresholds.
tail(sub_m, -2)
is all but the first two elements of sub_m
. head(sub_m, -2)
is all but the last two elements. So tail(sub_m,-2) - head(sub_m,-2)
is a vectorized way to calculate c(sub_m[3] - sub_m[1], sub_m[4] - sub_m[2], ...)
.
Upvotes: 1