1
votes

Suppose that I have three vectors of the same length

vec1 <- c(1,2,3,10)
vec2 <- c(1,4,5,8)
vec3 <- c("==","<=",">=","==")

I want to compare vec1[x] with vec2[x] using the operator in vec3[x], to check if all are true. My current solution is the following

vec1 <- c(1,2,3,10)
vec2 <- c(1,4,5,8)
vec3 <- c("==","<=",">=","==")

result <- TRUE

for (i in 1:4){
  if (vec3[i] == "=="){
    if (! vec1[i] == vec2[i]) {
      result <- FALSE
      break
    } 
  } else if (vec3[i] == "<=") {
    if (! vec1[i] <= vec2[i]) {
      result <- FALSE
      break
    } 
  } else if (vec3[i] == ">=") {
    if (! vec1[i] >= vec2[i]) {
      result <- FALSE
      break
    }
  }
}

print(result)

output is

[1] FALSE

It works but it's slow if vectors are larger and you have to do many. Is there a better way to do it? The vectors are sorted in such a way that the comparisons that are most likely to return FALSE come first. I'll add that in practice the vectors are of length 28. vec2 and vec3 are constant and vec1 is variable.

3
These are vectorized operations you can do vec1 == vec2 - akrun
and you can wrap with any - akrun

3 Answers

2
votes

This could be reduced to

f1 <- function(v1, v2, oper) {

  all(Reduce(`&`, lapply(oper, function(op) match.fun(op)(v1, v2))))

 }

f1(vec1, vec2, vec3)
#[1] FALSE
1
votes

Maybe you can try eval + call like this

all(mapply(function(op, a, b) eval(call(op, a, b)), vec3, vec1, vec2))

or Vectorize + do.call

all(Vectorize(do.call)(vec3, apply(cbind(vec1, vec2), 1, as.list)))
0
votes

One purrr option could be:

all(pmap_lgl(list(vec1, vec2, vec3), ~ exec(..3, ..1, ..2)))

[1] FALSE