R без учета регистра %в%

#r #data.table

#r #данные.таблица

Вопрос:

Я пытаюсь создать %in% подобную функцию без учета регистра. Я до сих пор создавал это:

 qs <- function(str, vec, na.rm = TRUE) {
  stopifnot("str must have length 1" = length(str) == 1)
  if(na.rm) {
    any(stringi::stri_detect_fixed(str, na.omit(vec), max_count = 1, opts_fixed = list(case_insensitive = TRUE)))
  } else {
    any(stringi::stri_detect_fixed(str, vec, max_count = 1, opts_fixed = list(case_insensitive = TRUE)))
  }
  

Для моего варианта использования мне нужно это векторизовать, чтобы я мог сделать:

 vecqs <- Vectorize(qs, "str")
  

Однако я читал, что Vectorize это довольно медленно. Я также читал о data.table::chmatch и fastmatch пакете. Оба они реализуют свою собственную %in% функцию типа ( chmatch для data.table ). Это было бы здорово, но я не знаю, как сделать chmatch без учета регистра.

Комментарии:

1. вы могли бы просто использовать tolower(X) %in% tolower(Y) , который не учитывал бы регистр, поскольку все преобразуется в нижний регистр. Только незначительные улучшения были бы получены при использовании Rcpp функции, использующей таблицу поиска ASCI или UTF-8, которая итеративно сопоставляет строки (если они вообще есть).

2. с помощью data.table можно создать фиктивный столбец dat[,to_match:=toupper(target][,to_match%chin%list_of_matches] , а затем удалить фиктивный столбец (или просто объединить)

3. Нет причин для назначения фиктивного столбца. Просто используйте tolower или toupper для каждого аргумента при сравнении %chin% .

Ответ №1:

Основываясь на комментариях выше, я пришел к относительно простому решению, приведенному ниже:

 #' Quick Search
#'
#' Quick case-insensitive search of strings in a character vector
#'
#' @param str a character vector: the values to be matched
#' @param vec a character vector: the values to be matched against
#'
#' @details Utilizes code{data.table::`%chin%`} to rapidly complete a case-insensitive search
#' through a character vector to return a logical vector of string detections.
#' Will always return TRUE or FALSE for each position of code{str} regardless of NA missing values 
#' in either provided vector. NA in code{str} will never match an NA value in code{vec}.
#'
#' @return a logical vector of length code{length(str)}
#'
#' @export
#' @importFrom data.table %chin%
#'
#' @examples
#' x <- c("apple","banana","cherry",NA)
#' "apple" %qsin% x
#' c("APPLE","BANANA","coconut", NA) %qsin% x
#'
`%qsin%` <- function(str, vec) {
  tolower(str) %chin% na.omit(tolower(vec))
}
  

Комментарии:

1. возможно, потребуется добавить явное, if (!require("data.table")) ... если это не используется в контексте, где data.table обязательно будет загружено. (Я пропустил data.table:: в документах в первый раз)