用字符串中的单个数字替换数字范围
replace range of numbers with single numbers in a character string
有没有办法用字符串中的单个数字替换数字范围?数字可以从 n-n,最有可能在 1-15 左右,也可以是 4-10。
范围可以用 a) -
表示
a <- "I would like to buy 1-3 cats"
或用词 b) 例如:to, bis, jusqu'à
b <- "I would like to buy 1 jusqu'à 3 cats"
结果应该是这样的
"I would like to buy 1,2,3 cats"
我发现了这个: 但不能在 R 中真正使用它。
事实上,这有点棘手,除非有人已经编写了执行此操作的程序包(我不知道)。
a <- "I would like to buy 1-3 cats"
pos <- unlist(gregexpr("\d+\D+", a))
a_split <- unlist(strsplit(a, ""))
replacement <- paste(seq.int(a_split[pos[1]], a_split[pos[2]]), collapse = ",")
gsub("\d+\D+\d+", replacement, a)
# [1] "I would like to buy 1,2,3 cats"
编辑:显示相同的解决方案适用于两个数字之间的任意非数字字符:
b <- "I would like to buy 1 jusqu'à 3 cats"
pos_b <- unlist(gregexpr("\d+\D+", b))
b_split <- unlist(strsplit(b, ""))
replacement <- paste(seq.int(b_split[pos_b[1]], b_split[pos_b[2]]), collapse = ",")
gsub("\d+\D+\d+", replacement, b)
# [1] "I would like to buy 1,2,3 cats"
如果您愿意,您可以为非数字字符的 运行 添加任意要求。如果您需要这方面的帮助,请分享数字之间的单词或符号的限制是什么!
不是最有效的,但是...
s <- c("I would like to buy 1-3 cats",
"I would like to buy 1 jusqu'à 3 cats",
"foo 22-33",
"quux 11-3 bar")
gre <- gregexpr("([0-9]+(-| to | bis | jusqu'à )[0-9]+)", s)
gre2 <- gregexpr('[0-9]+', regmatches(s, gre))
regmatches(s, gre) <- lapply(regmatches(regmatches(s, gre), gre2),
function(a) paste(do.call(seq, as.list(as.integer(a))), collapse = ","))
s
# [1] "I would like to buy 1,2,3 cats" "I would like to buy 1,2,3 cats"
# [3] "foo 22,23,24,25,26,27,28,29,30,31,32,33" "quux 11,10,9,8,7,6,5,4,3 bar"
gsubfn 包中的 gsubfn
类似于 gsub
但它不是用替换字符串替换匹配项,而是允许用户指定一个函数(可能使用此处完成的公式表示法)。然后它将匹配项传递给正则表达式中的捕获组,即正则表达式括号部分的匹配项作为单独的参数,并用函数的输出替换整个匹配项。因此我们匹配 "(\d+)(-| to | bis | jusqu'à )(\d+)"
导致三个捕获组,因此函数有 3 个参数。在函数中,我们将 seq
与其中的第一个和第三个一起使用。请注意,seq
可以采用字符参数并将它们解释为数字,因此我们不必将参数转换为数字。
因此我们得到这个 one-liner:
library(gsubfn)
s <- c(a, b) # test input strings
gsubfn("(\d+)(-| to | bis | jusqu'à )(\d+)", ~ paste(seq(..1, ..3), collapse = ","), s)
给予:
[1] "I would like to buy 1,2,3 cats" "I would like to buy 1,2,3 cats"
有没有办法用字符串中的单个数字替换数字范围?数字可以从 n-n,最有可能在 1-15 左右,也可以是 4-10。
范围可以用 a) -
表示a <- "I would like to buy 1-3 cats"
或用词 b) 例如:to, bis, jusqu'à
b <- "I would like to buy 1 jusqu'à 3 cats"
结果应该是这样的
"I would like to buy 1,2,3 cats"
我发现了这个:
事实上,这有点棘手,除非有人已经编写了执行此操作的程序包(我不知道)。
a <- "I would like to buy 1-3 cats"
pos <- unlist(gregexpr("\d+\D+", a))
a_split <- unlist(strsplit(a, ""))
replacement <- paste(seq.int(a_split[pos[1]], a_split[pos[2]]), collapse = ",")
gsub("\d+\D+\d+", replacement, a)
# [1] "I would like to buy 1,2,3 cats"
编辑:显示相同的解决方案适用于两个数字之间的任意非数字字符:
b <- "I would like to buy 1 jusqu'à 3 cats"
pos_b <- unlist(gregexpr("\d+\D+", b))
b_split <- unlist(strsplit(b, ""))
replacement <- paste(seq.int(b_split[pos_b[1]], b_split[pos_b[2]]), collapse = ",")
gsub("\d+\D+\d+", replacement, b)
# [1] "I would like to buy 1,2,3 cats"
如果您愿意,您可以为非数字字符的 运行 添加任意要求。如果您需要这方面的帮助,请分享数字之间的单词或符号的限制是什么!
不是最有效的,但是...
s <- c("I would like to buy 1-3 cats",
"I would like to buy 1 jusqu'à 3 cats",
"foo 22-33",
"quux 11-3 bar")
gre <- gregexpr("([0-9]+(-| to | bis | jusqu'à )[0-9]+)", s)
gre2 <- gregexpr('[0-9]+', regmatches(s, gre))
regmatches(s, gre) <- lapply(regmatches(regmatches(s, gre), gre2),
function(a) paste(do.call(seq, as.list(as.integer(a))), collapse = ","))
s
# [1] "I would like to buy 1,2,3 cats" "I would like to buy 1,2,3 cats"
# [3] "foo 22,23,24,25,26,27,28,29,30,31,32,33" "quux 11,10,9,8,7,6,5,4,3 bar"
gsubfn
类似于 gsub
但它不是用替换字符串替换匹配项,而是允许用户指定一个函数(可能使用此处完成的公式表示法)。然后它将匹配项传递给正则表达式中的捕获组,即正则表达式括号部分的匹配项作为单独的参数,并用函数的输出替换整个匹配项。因此我们匹配 "(\d+)(-| to | bis | jusqu'à )(\d+)"
导致三个捕获组,因此函数有 3 个参数。在函数中,我们将 seq
与其中的第一个和第三个一起使用。请注意,seq
可以采用字符参数并将它们解释为数字,因此我们不必将参数转换为数字。
因此我们得到这个 one-liner:
library(gsubfn)
s <- c(a, b) # test input strings
gsubfn("(\d+)(-| to | bis | jusqu'à )(\d+)", ~ paste(seq(..1, ..3), collapse = ","), s)
给予:
[1] "I would like to buy 1,2,3 cats" "I would like to buy 1,2,3 cats"