首页 > 解决方案 > 如何避免内容相似的长链

问题描述

我目前正在编写一个 R 函数get_line_type(line)来输出行的类型(字符串)。对于每个当前可能的类型,都有一个形式的函数,is_TYPENAME_line(line)它返回一个布尔值,指示该行是否属于这种特定类型。将这些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在链中添加另一个 -statement 来完成这项工作,但我想知道是否有更优雅的方法来解决这个问题,因为每个条件看起来都非常相似。

标签: rif-statementdesign-patternsmatching

解决方案


我不确定这是否是您正在寻找的,但这里有一些需要考虑的事情:

创建一个包含您在函数中包含的“TYPENAMES”的向量。然后,您可以动态构建这些函数并将其放置在名为funcList.

您的get_line_type函数可以调用所有函数并line作为参数提供。当您返回TRUEFALSE从这些函数返回时,结果可以很容易地简化。

我在评论中注意到您可能有两个带有空格的单词(例如,“产品搜索”)。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")
}

推荐阅读