如何在 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"
然后我通过执行以下操作确定上述每个值是一组字母还是数字(如果它是一组数字,我得到输出 FALSE
,TRUE
如果是一组字母):
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
假设我有这样一个字符串: 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"
然后我通过执行以下操作确定上述每个值是一组字母还是数字(如果它是一组数字,我得到输出 FALSE
,TRUE
如果是一组字母):
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