R 逐步搜索分层查找的字符串 table 以进行匹配

R progressively search string of a hierarchical lookup table for matches

我正在与 OPS codes 合作,它对在医院执行的程序类型进行编码。 OPS 编码列表具有 X-XXX.XX 形式的层次结构,其中 X 是数字。编码结构是分层的,也就是说,第一个 X- 是一个大集合,然后 XXX 表示第一个 X-,最后一个 .XX 中的子集类型的过程表示 XXX

的子专业化

所以代码可能是 X-XXXX-XXX.X-XXX.XX-XXX.XX

我的问题是我们使用的程序将代码结构折叠为 XXXXXXXXXXXXXXXX,我想将折叠的 llokup 与未折叠的 llokup 相匹配table 个定义。

所以我想要一个例程来检查每个数字,然后在执行匹配时继续下一个数字。 grepl 不会,因为 5381 会匹配 65381(未折叠的是 5-381 和 6-538.1),这是完全不同的过程。我需要一些能够将字符匹配到字符(第一个数字第二个数字等)并尊重字符位置的东西。

当找不到完全匹配时,应该return第一个匹配相同字符位置的匹配。

伪代码中的更多示例

which("5381" %in% c("65381","53811", "5382")) 应该 return 2 因为第二项匹配提供的所有可用字符

which("5381" %in% c("538110","538111", "538221")) 应该 return 1(因为它是第一个匹配项,c() 中的查找 table 已排序。

which("5381." %in% c("5381","538111", "538121"))应该return1(因为是第一个匹配,c()里面的lookup table是排序的,注意忽略句点在比赛中

which("5381.1" %in% c("5381","538111", "538112")) 应该 return 2(因为它是匹配所有可用五个字符的第一个匹配项,而我们没有第五个字符。

我知道这不是 SO 中问题的最佳示例,但我愿意改进这个问题。

这可能太复杂了,但它确实有效。
首先定义一个泛型来将输入字符串转换为 OPS 格式。然后有一个匹配函数检查 x 是否有 y 作为子字符串。

注意匹配函数不检查x是否是y的子串,恰恰相反

as.ops <- function(x, ...) UseMethod("as.ops")
as.ops.default <- function(x, ...){
  warning("The default method coerces its argument to character and calls the character method")
  as.ops.character(as.character(x))
}
as.ops.character <- function(x, ...){
  x <- gsub("[^[:digit:]]", "", x)
  ops1 <- substr(x, 1, 1)
  ops2 <- substr(x, 2, 4)
  ops3 <- substring(x, 5)
  y <- character(length(x))
  n <- findInterval(nchar(x), c(0, 1, 4, 7))
  y[n == 1] <- x[n == 1]
  y[n != 1] <- paste(ops1[n != 1], ops2[n != 1], sep = "-")
  o3 <- nchar(ops3) > 0
  y[n == 3 & o3] <- paste(y[n == 3 & o3], ops3[n == 3 & o3], sep = ".")
  y
}
ops_match <- function(x, y){
  xo <- as.ops(x)
  yo <- as.ops(y)
  i <- (xo %in% yo) | grepl(yo, xo)
  which(i)
}

x1 <- c("65381","53811", "5382")
x2 <- c("538110","538111", "538221")
x3 <- c("5381","538111", "538121")
x4 <- c("5381","538111", "538112")
y1 <- y2 <- "5381"
y3 <- "5381."
y4 <- "5381.1"

ops_match(x1, y1)
ops_match(x2, y2)
ops_match(x3, y3)
ops_match(x4, y4)