如何在 R 中的字母数字字符串中获取 number/alphabet 索引模式?

How to get the number/alphabet index pattern in an alphanumeric string in R?

假设我有这样一个字符串: xyz45kpt793rsdwq1

我需要像这样计算其等效的字母和数字序列模式作为输出: 3a2n3a3n5a1n

其中,
“a”代表字母
"n"代表数字
并且数值告诉连续的字母或数字的计数

这是我尝试过的:

strsplit("xyz45kpt793rsdwq1", "(?=[A-Za-z])(?<=[0-9])|(?=[0-9])(?<=[A-Za-z])", perl=TRUE)

我得到的输出为:

[[1]]
[1] "xyz"   "45"    "kpt"   "793"   "rsdwq" "1" 

然后我通过执行以下操作确定上述每个值是一组字母还是数字(如果它是一组数字,我得到输出 FALSETRUE如果是一组字母):

x <- strsplit("xyz45kpt793rsdwq1", "(?=[A-Za-z])(?<=[0-9])|(?=[0-9])(?<=[A-Za-z])", perl=TRUE)[[1]][2]
grepl("^[A-Za-z]+$", x, perl = T)

我对 6 个元素中的每一个都做了这个。在这里,我展示了地址为 [[1]][2] 的第二个元素的代码作为示例。

接下来,我通过nchar(x)求出了上面每一个的长度。 现在我可以将它们组合起来,为第一个元素创建输出 3a,为第二个元素创建输出 2n,依此类推。 最终我可以将所有这些结合起来以获得所需的模式输出 3a2n3a3n5a1n

但是我试过的这种方法似乎有点矫枉过正而且太冗长了。如果我在数据框中有一整列字符串,那么做同样的事情会变得太复杂——我需要为每个字符串计算这个模式。

任何人都可以帮助提供一行代码,以更有效的方式执行此操作吗?

您可以在此处使用 gsubfn

library(gsubfn)
x <- "xyz45kpt793rsdwq1"
gsubfn("(\d+)|(\p{L}+)", function(x,y) ifelse(nzchar(x), paste0(nchar(x),"n"), paste0(nchar(y),"a")), x, perl=TRUE)
# => [1] "3a2n3a3n5a1n"

PCRE 正则表达式(perl=TRUE 启用 PCRE 正则表达式)- (\d+)|(\p{L}+) - 匹配并捕获第 1 组 (x) 任何一位或多位数字,或捕获任何一位或更多字母进入第 2 组 (y)。如果第 1 组匹配 (nzchar(x)),则替换为匹配的长度 (nchar(x)) 和 n。否则,第 2 组匹配,替换为组的长度 + a.

不使用库的解决方案。我认为您的方法不会太冗长,您可以将现有逻辑放入函数中并将其应用于数据框列:

x <- data.frame(strings = c("xyz45kpt793rsdwq1", "abs12345djf"), stringsAsFactors = FALSE)

my_fun <- function(strings) {
  matches <- sapply(strings, strsplit, "(?=[A-Za-z])(?<=[0-9])|(?=[0-9])(?<=[A-Za-z])", perl=TRUE)
  sapply(matches, function(x) {
    y <- ifelse(substr(x, 1, 1) %in% letters, paste0(nchar(x), "a"), paste0(nchar(x), "n"))
    paste(y, collapse = "")
  })
}

x$new_strings <- my_fun(x$strings)
x

输出:

            strings  new_strings
1 xyz45kpt793rsdwq1 3a2n3a3n5a1n
2       abs12345djf       3a5n3a