R:解析带有特定文本的嵌套括号

时间:2018-07-31 16:57:02

标签: r nested parent-child parentheses

我对R编程比较陌生,但是在从句法分析的历史语言语料库中提取文本方面有一个特定的问题。这个问题应该很容易解决,但是我还是无法解决。我的问题基本上是该问题的一个更具体的变化:R: parse nested parentheses

我想解析R中的嵌套括号。这是一些数据的示例:

(sometext(NP-SBJ(D+N_THYSTORYE)(PP(P_OF)(NP(NPR_REYNARD)(NP-PRN(D_THE)(N_FOXE)))))sometext)

我想从该字符串中提取所有以“ NP”开头的(可能嵌套的)子字符串,因此结果应为

(NP-SBJ(D+N_THYSTORYE)(PP(P_OF)(NP(NPR_REYNARD)(NP-PRN(D_THE)(N_FOXE)))))

(NP(NPR_REYNARD)(NP-PRN(D_THE)(N_FOXE)))

(NPR_REYNARD)

(NP-PRN(D_THE)(N_FOXE))

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

这可能不是最有效的,但是这里有一个函数可以提取匹配的括号之间的“令牌”或字符串。

find_tokens <- function(s) {
  stopifnot(length(s)==1)
  mm <- gregexpr("[)()]", s)
  stack <- numeric()
  starts <- numeric()
  stops <- numeric()
  Map(function(i, v) {
    if(v=="(") {
      stack <<- c(stack, i)
    } else if (v==")") {
      starts <<- c(starts, tail(stack, 1))
      stops <<- c(stops, i)
      stack <<- stack[-length(stack)]
    }
  }, mm[[1]], regmatches(s, mm)[[1]])
  rev(substring(s, starts, stops))
}

这将提取所有内容。如果您只想保留以((NP)开头的值,则可以grep此列表​​

grep("^\\(NP", find_tokens(s), value=TRUE)
# [1] "(NP-SBJ(D+N_THYSTORYE)(PP(P_OF)(NP(NPR_REYNARD)(NP-PRN(D_THE)(N_FOXE)))))"
# [2] "(NP(NPR_REYNARD)(NP-PRN(D_THE)(N_FOXE)))"                                 
# [3] "(NP-PRN(D_THE)(N_FOXE))"                                                  
# [4] "(NPR_REYNARD)"  

这是find_tokens的另一种可能的实现,它可能更高效,可以更好地支持列表中的多个字符串。

find_tokens <- function(s) {
  mm <- gregexpr("[)()]", s)
  vv <- regmatches(s, mm)
  extr <- function(x, mm, vv) {
    open_i <- 0
    shut_i <- 0
    open <- numeric(length(vv)/2)
    shut <- numeric(length(vv)/2)
    close <- numeric(length(vv)/2)
    for(i in seq_along(mm)) {
      if (vv[i]=="(") {
        open_i <- open_i + 1
        shut_i <- shut_i + 1
        open[open_i] <- mm[i]
        shut[shut_i] <- open_i
      } else if (vv[i]==")") {
        close[shut[shut_i]] <- mm[i]
        shut_i <- shut_i - 1
      }
    }
    substring(x, open, close)
  }
  unname(Map(extr, s, mm, vv))
}

然后您将使用

lapply(find_tokens(s), function(x) grep("^\\(NP", x, value=TRUE))