Фон
У меня есть забавная функция, которая сравнивает векторы в списке, используя all.equal
.Поскольку я использую all.equal
, я бы хотел передать соответствующие all.equal
аргументы через многоточие.Без необходимости передавать что-либо в all.equal
функция работает как нужно.
Цели функции
- Функция предназначена для предоставления модифицированной версии вызова
all.equal
, работающего с любым числомвекторы - Каждый из векторов может иметь любое количество элементов;однако, если все векторы не имеют одинаковую длину, функция вернет false.
- Функция должна иметь возможность использовать аргументы, доступные в
all.equal
.Например, векторы c(1.1, 2)
, c(1, 2)
и c(1.3, 2)
будут считаться равными, если указан аргумент tolerance
с правильным значением. Вопрос касается того, как заставить это работать.
Пример
Сравнение 1000 векторов, каждый из которых состоит из трех целых чисел.
compare_multiple_vectors(x = lapply(
X = vector(mode = "list", length = 1e3),
FUN = function(...) {
c(1, 2, 3)
}
))
# [1] TRUE
Проблема / желаемые результаты
all.equal
, вызванные с tolerance = 1
в следующем списке векторов, вернут ожидаемые TRUE
all.equal(c(1,2), c(1,1), tolerance = 1)
# [1] TRUE
tolerance = 1
аргумент не может быть отфильтрован внутри Reduce
.
compare_multiple_vectors(x = list(c(1,2), c(1,1)), tolerance = 1)
# [1] FALSE
желаемый результат должен быть 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)
}
}
Примечания
Мне интересно использовать многоточие и оставить исходный вызов таким, какой он есть с
compare_multiple_vectors(x = list_of_vectors_to_compare,
... # all.equal arguments
)