用正则表达式提取ngram

时间:2015-06-23 12:40:21

标签: regex r stringi

Karl Broman的帖子:https://kbroman.wordpress.com/2015/06/22/randomized-hobbit-2/让我玩正则表达式和ngrams只是为了好玩。我试图用正则表达式提取2克。我知道有解析器可以做到这一点,但我对正则表达式逻辑很感兴趣(即,这是一个我无法满足的自我挑战)。

下面我给出一个最小的例子和所需的输出。我尝试的问题是2折:

  1. 克(单词)被吃掉,下次通过时无法使用。 如何才能将它们提供给第二次传递?(例如,我希望likelike toast中之前已经消耗I like后可用(?:\\s*)

  2. 我无法在未捕获的单词之间创建空格(即使我使用"(\\b[A-Za-z']+\\s)(\\b[A-Za-z']+)",也要注意输出中的尾随空格)。 我怎么能不捕获第n个(在这种情况下是第二个)单词的尾随空格?我知道这可以简单地使用:\\w进行2克但我想扩展n-gram的解决方案。 PS我知道',但我不认为下划线和数字是单词部分,但请将library(stringi) x <- "I like toast and jam." stringi::stri_extract_all_regex( x, pattern = "((\\b[A-Za-z']+\\b)(?:\\s*)){2}" ) ## [[1]] ## [1] "I like " "toast and " 视为单词部分。

  3. MWE:

    ## [[1]]
    ## [1] "I like"  "like toast"    "toast and"  "and jam"
    

    所需的输出:

    mMyListView.getRefreshableView().getLayoutParams().height=RelativeLayout.LayoutParams.WRAP_CONTENT;
    mMyListView.getRefreshableView().requestLayout();

2 个答案:

答案 0 :(得分:7)

这是使用基本R正则表达式的一种方式。这可以很容易地扩展到处理任意n-gram。诀窍是将捕获组置于正向前瞻断言中,例如,(?=(my_overlapping_pattern))

x <- "I like toast and jam."
pattern <- "(?=(\\b[A-Za-z']+\\b \\b[A-Za-z']+\\b))"
matches<-gregexpr(pattern, x, perl=TRUE)
# a little post-processing needed to get the capture groups with regmatches
attr(matches[[1]], 'match.length') <- as.vector(attr(matches[[1]], 'capture.length')[,1])
regmatches(x, matches)

# [[1]]
# [1] "I like"     "like toast" "toast and"  "and jam"

答案 1 :(得分:2)

实际上,有一个应用程序:quanteda包(用于文本数据的定量分析)。我的合着者Paul Nulty和我正在努力改进这一点,但它很容易处理你描述的用例。

install.packages("quanteda")
require(quanteda)
x <- "I like toast and jam."
> ngrams(x, 2)
## [[1]]
## [1] "i_like"     "like_toast" "toast_and"  "and_jam"   
ngrams(x, n = 2, concatenator = " ", toLower = FALSE)
## [[1]]
## [1] "I like"     "like toast" "toast and"  "and jam"   

不需要痛苦的正则表达式!