如何反转 R 中嵌套括号内的字符?
How do I reverse characters within nested brackets in R?
我正在尝试解决以下问题:
"编写一个函数来反转输入字符串中(可能嵌套的)括号中的字符。
输入字符串将始终格式正确且具有匹配 ()s。
例子
对于
inputString = "(bar)",
输出应该是
solution(inputString) = "rab";
对于
inputString = "foo(bar)baz",
输出应该是
solution(inputString) = "foorabbaz";
对于
inputString = "foo(bar)baz(blim)",
输出应该是
solution(inputString) = "foorabbazmilb";
对于
inputString = "foo(bar(baz))blim",
输出应该是
solution(inputString) = "foobazrabblim".
因为
"foo(bar(baz))blim"
变成
"foo(barzab)blim"
然后
"foobazrabblim".
现在我已经设法解决了只有一对括号的简单情况的问题——即未嵌套且没有第二对。我的代码:
solution <- function(inputString) {
a <- unlist(strsplit(x=inputString,split=""))
bracket.indices <- grep(pattern="\(|\)",x=a)
a[(bracket.indices[1] + 1): (bracket.indices[2] - 1)] <- rev(a[(bracket.indices[1] + 1): (bracket.indices[2] - 1)])
return(paste(a <- a[-bracket.indices]))
}
所以我首先拆分字符串,以便我可以通过索引访问各个元素。接下来,我使用 grep 来识别括号的索引,然后使用这些索引访问括号内的字符并使用 rev() 反转它们。最后,我去掉了括号,然后使用 paste() 将拆分后的字符串折叠回普通字符串。显然,如果有第二对括号——例如我们有
inputString = "foo(bar)baz(blim)"
我的代码无法运行,因为我假设 bracket.indices 只有两个元素并相应地访问了它们。更重要的是,我的代码显然不适用于嵌套括号,因为嵌套括号的内容需要与外括号的内容一起反转。
可能在解决这个简单案例的问题时,我只是扭曲了正确的解决方案,但由于更大的问题对我来说有点莫名其妙,所以从简单案例开始是我认为最好的开始.有什么帮助吗? (首选 Base R)
1) 假设输入是一个字符串 x,任何 (...) 出现仅包含单词字符和其他 (...) 的混合,并且没有不平衡的括号,然后在其中存在一个 (,使用 gsubfn 在内部括号内匹配和反转由单词字符组成的字符串(\w
- 参见 ?regex 的定义)。gsubfn 类似于 gsub 除了替换字符串可以是一个函数,它在匹配中输入捕获组并输出替换。
下面定义的 strrep 函数反转字符串。请参阅 https://www.r-bloggers.com/2019/05/four-ways-to-reverse-a-string-in-r/ and How to Reverse a string in R 以及其他几种反转字符串的方法。
library(gsubfn)
strrev <- function(x) intToUtf8(rev(utf8ToInt(x)))
rev_paren <- function(x) {
while(grepl("(", x, fixed = TRUE)) {
x <- gsubfn("\((\w*?)\)", strrev, x)
}
x
}
rev_paren("foo(bar(baz))blim")
## [1] "foobazrabblim"
2) 没有循环但使用递归计算的变体是:
library(gsubfn)
strrev <- function(x) intToUtf8(rev(utf8ToInt(x)))
rev_paren <- function(x) {
if (grepl("(", x, fixed = TRUE))
Recall(gsubfn("\((\w*?)\)", strrev, x))
else x
}
rev_paren("foo(bar(baz))blim")
## [1] "foobazrabblim"
3) 这是一个基本的解决方案。它比上面的要长,但没有依赖关系。
strrev <- function(x) intToUtf8(rev(utf8ToInt(x)))
rev_paren <- function(x) {
while(grepl("(", x, fixed = TRUE)) {
s <- strcapture("\((\w*)\)", x, list(character(0)))[[1]]
x <- sub(sprintf("(%s)", s), strrev(s), x, fixed = TRUE)
}
x
}
rev_paren("foo(bar(baz))blim")
## [1] "foobazrabblim"
字符向量
在任何这些情况下,如果 v 是字符向量,我们都可以使用以下内容。
sapply(v, rev_paren)
或
Vectorize(rev_paren)(v)
我正在尝试解决以下问题:
"编写一个函数来反转输入字符串中(可能嵌套的)括号中的字符。
输入字符串将始终格式正确且具有匹配 ()s。
例子
对于
inputString = "(bar)",
输出应该是
solution(inputString) = "rab";
对于
inputString = "foo(bar)baz",
输出应该是
solution(inputString) = "foorabbaz";
对于
inputString = "foo(bar)baz(blim)",
输出应该是
solution(inputString) = "foorabbazmilb";
对于
inputString = "foo(bar(baz))blim",
输出应该是
solution(inputString) = "foobazrabblim".
因为
"foo(bar(baz))blim"
变成
"foo(barzab)blim"
然后
"foobazrabblim".
现在我已经设法解决了只有一对括号的简单情况的问题——即未嵌套且没有第二对。我的代码:
solution <- function(inputString) {
a <- unlist(strsplit(x=inputString,split=""))
bracket.indices <- grep(pattern="\(|\)",x=a)
a[(bracket.indices[1] + 1): (bracket.indices[2] - 1)] <- rev(a[(bracket.indices[1] + 1): (bracket.indices[2] - 1)])
return(paste(a <- a[-bracket.indices]))
}
所以我首先拆分字符串,以便我可以通过索引访问各个元素。接下来,我使用 grep 来识别括号的索引,然后使用这些索引访问括号内的字符并使用 rev() 反转它们。最后,我去掉了括号,然后使用 paste() 将拆分后的字符串折叠回普通字符串。显然,如果有第二对括号——例如我们有
inputString = "foo(bar)baz(blim)"
我的代码无法运行,因为我假设 bracket.indices 只有两个元素并相应地访问了它们。更重要的是,我的代码显然不适用于嵌套括号,因为嵌套括号的内容需要与外括号的内容一起反转。
可能在解决这个简单案例的问题时,我只是扭曲了正确的解决方案,但由于更大的问题对我来说有点莫名其妙,所以从简单案例开始是我认为最好的开始.有什么帮助吗? (首选 Base R)
1) 假设输入是一个字符串 x,任何 (...) 出现仅包含单词字符和其他 (...) 的混合,并且没有不平衡的括号,然后在其中存在一个 (,使用 gsubfn 在内部括号内匹配和反转由单词字符组成的字符串(\w
- 参见 ?regex 的定义)。gsubfn 类似于 gsub 除了替换字符串可以是一个函数,它在匹配中输入捕获组并输出替换。
下面定义的 strrep 函数反转字符串。请参阅 https://www.r-bloggers.com/2019/05/four-ways-to-reverse-a-string-in-r/ and How to Reverse a string in R 以及其他几种反转字符串的方法。
library(gsubfn)
strrev <- function(x) intToUtf8(rev(utf8ToInt(x)))
rev_paren <- function(x) {
while(grepl("(", x, fixed = TRUE)) {
x <- gsubfn("\((\w*?)\)", strrev, x)
}
x
}
rev_paren("foo(bar(baz))blim")
## [1] "foobazrabblim"
2) 没有循环但使用递归计算的变体是:
library(gsubfn)
strrev <- function(x) intToUtf8(rev(utf8ToInt(x)))
rev_paren <- function(x) {
if (grepl("(", x, fixed = TRUE))
Recall(gsubfn("\((\w*?)\)", strrev, x))
else x
}
rev_paren("foo(bar(baz))blim")
## [1] "foobazrabblim"
3) 这是一个基本的解决方案。它比上面的要长,但没有依赖关系。
strrev <- function(x) intToUtf8(rev(utf8ToInt(x)))
rev_paren <- function(x) {
while(grepl("(", x, fixed = TRUE)) {
s <- strcapture("\((\w*)\)", x, list(character(0)))[[1]]
x <- sub(sprintf("(%s)", s), strrev(s), x, fixed = TRUE)
}
x
}
rev_paren("foo(bar(baz))blim")
## [1] "foobazrabblim"
字符向量
在任何这些情况下,如果 v 是字符向量,我们都可以使用以下内容。
sapply(v, rev_paren)
或
Vectorize(rev_paren)(v)