I have a fun function that compares vectors within a list using all.equal
. As I'm making use of the all.equal
I would like to pass relevant all.equal
arguments via ellipsis. Without the need to pass anything to all.equal
the function works as desired.
all.equal
call working on any number of vectorsall.equal
. For instance vectors c(1.1, 2)
, c(1, 2)
and c(1.3, 2)
will be considered equal if tolerance
argument with the right value is provided. The question is concerned with getting this to work.Comparing 1,000 vectors, each consisting of three integers.
compare_multiple_vectors(x = lapply(
X = vector(mode = "list", length = 1e3),
FUN = function(...) {
c(1, 2, 3)
}
))
# [1] TRUE
all.equal
called with tolerance = 1
on the following list of vectors will return expected TRUE
all.equal(c(1,2), c(1,1), tolerance = 1)
# [1] TRUE
The tolerance = 1
argument fails to filter down to inside Reduce
.
compare_multiple_vectors(x = list(c(1,2), c(1,1)), tolerance = 1)
# [1] FALSE
The desired result should be TRUE
.
#' @title Compare Values of Multiple Vectors
#'
#' @description The function compares values across multiple vectors using
#' \code{\link[base]{all.equal}}.
#'
#' @param x Alist of vectors to compare
#' @param ... as in \code{\link[base]{all.equal}}
#'
#' @return A logical
#'
#' @export
#'
#' @importFrom checkmate assert_atomic_vector
#'
#' @examples
#' # Returns TRUE
#' compare_multiple_vectors(c(1,1,1), c(1,1,1))
#' # Returns FALSE
#' compare_multiple_vectors(c(1,1,1), c(1,1,1), c(1,2,1))
#' # Returns FALSE
#' compare_multiple_vectors(c(1,2,3), c(3,2,1))
compare_multiple_vectors <- function(x, ...) {
# Check if all elements of x are atomic vectors
Vectorize(FUN = checkmate::assert_atomic_vector,
vectorize.args = "x")(x)
# Compare list elements
Reduce(
f = function(a, b, ...) {
if (isTRUE(all.equal(target = a, current = b, ...))) {
a
} else {
FALSE
}
},
x = x
) -> res_red
# Return results
if (isFALSE(res_red)) {
return(FALSE)
} else {
return(TRUE)
}
}
I'm interested in making use of ellipsis and leaving the initial call the way it is with
compare_multiple_vectors(x = list_of_vectors_to_compare,
... # all.equal arguments
)
I think just need a little change:
compare_multiple_vectors <- function(x, ...) {
# Check if all elements of x are atomic vectors
Vectorize(FUN = checkmate::assert_atomic_vector,
vectorize.args = "x")(x)
# Compare list elements
Reduce(
f = function(a, b) { # <===================== Remove *...*
if (isTRUE(all.equal(target = a, current = b, ...))) {
a
} else {
FALSE
}
},
x = x
) -> res_red
# Return results
if (isFALSE(res_red)) {
return(FALSE)
} else {
return(TRUE)
}
}
The arguments f of Reduce seems to have a signature like function(x, y). So Reduce will ignore ... in f. If remove the ellipsis of f, ... will reference from the outer space, and will have the right result you want.