Как избежать длинных цепочек с похожим содержанием - PullRequest
0 голосов
/ 21 марта 2020

В настоящее время я пишу функцию R get_line_type(line) для вывода типа строки (строки). Для каждого возможного в настоящее время типа есть функция вида is_TYPENAME_line(line), которая возвращает логическое значение, указывающее, относится ли строка к указанному типу c. Объединение этих is_TYPENAME_line функций воедино создает функцию get_line_type(line) и в настоящее время выглядит следующим образом

is_fish_line <- function(line) {
  return (any(grep("fish", line)))
}

is_mouse_line <- function(line) {
  return (any(grep("mouse", line)))
}

get_line_type <- function(line) {
  identified_types <- character(0)

  if(is_fish_line(line)) { identified_types[length(identified_types) + 1] <- "FISH" }
  if(is_mouse_line(line)) { identified_types[length(identified_types) + 1] <- "MOUSE" }

  if (length(identified_types) > 1) {
    stop("Matched multiple types: ", paste(identified_types, collapse = ", "), "\t", "Line: ", line)
  }

  return(if(length(identified_types) == 1) identified_types[1] else "UNKOWN")
}

Этот код работает следующим образом

> get_line_type("The fish seems happy.")
[1] "FISH"
> get_line_type("A mouse is living in this house.")
[1] "MOUSE"
> get_line_type("The tiger is the king of the jungle.")
[1] "UNKOWN"
> get_line_type("The fish and the mouse are friends.")
Error in get_line_type("The fish and the mouse are friends.") : 
  Matched multiple types: FISH, MOUSE Line: The fish and the mouse are friends.

Внутри функции создается список identified_types с именами всех идентифицированных типов для строки аргумента. Если тип не найден, возвращается UNKOWN. Если был идентифицирован ровно один тип, возвращается идентифицированный тип. Если было идентифицировано более одного типа, возникает ошибка (это не должно происходить).

В будущем список возможных типов может увеличиться, и я могу просто добавить еще одно if заявление в цепочку, чтобы сделать эту работу, но мне было интересно, есть ли более элегантный подход к этому, так как каждое условие выглядит так похоже.

1 Ответ

1 голос
/ 22 марта 2020

Я не уверен, что это то, что вы ищете, но вот что нужно учитывать:

Создайте вектор, содержащий «ТИПЫ», которые вы включаете в свои функции. Затем вы можете динамически построить эти функции и поместить их в именованный список с именем funcList.

Ваша функция get_line_type может вызывать все функции и предоставлять line в качестве аргумента. Результаты можно легко упростить, если вы вернете TRUE или FALSE из этих функций.

Я заметил в комментарии, что у вас могут быть два слова с пробелом (например, «поиск товара»). В all_types вам нужно поставить подчеркивание между этими словами, чтобы создать полезную функцию без пробелов. Кроме того, identified_types можно изменить, чтобы удалить подчеркивания при необходимости.

all_types <- c("fish", "mouse")
funcList <- lapply(all_types, function(x) eval(parse(text = paste0('is_', x, '_line'))))
names(funcList) <- all_types

get_line_type <- function(line) {
  lst <- lapply(funcList, do.call, list(line))
  identified_types <- names(lst[unlist(lst)])
  if (length(identified_types) > 1) {
    stop("Matched multiple types: ", paste(identified_types, collapse = ", "), "\t", "Line: ", line)
  }
  return(if(length(identified_types) == 1) identified_types[1] else "UNKNOWN")
}
...