如何反转 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)