Fabled
Fabled

Reputation: 79

Construct loop with multiple conditions

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

Answers (1)

Gregor Thomas
Gregor Thomas

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

Related Questions