如何提取最长的匹配?

时间:2018-05-21 17:28:04

标签: r regex stringr purrr

考虑这个简单的例子

library(stringr)
library(dplyr)

dataframe <- data_frame(text = c('how is the biggest ??',
                                 'really amazing stuff'))

# A tibble: 2 x 1
  text                 
  <chr>                
1 how is the biggest ??
2 really amazing stuff 

我需要根据regex表达式提取一些术语,但只提取最长的术语

到目前为止,我只能使用str_extract提取第一场比赛(不一定是最长的)。

> dataframe %>% mutate(mymatch = str_extract(text, regex('\\w+')))
# A tibble: 2 x 2
  text                  mymatch
  <chr>                 <chr>  
1 how is the biggest ?? how    
2 really amazing stuff  really 

我尝试使用str_extract_all,但我找不到有效的语法。 输出应该是:

# A tibble: 2 x 2
  text                  mymatch
  <chr>                 <chr>  
1 how is the biggest ?? biggest
2 really amazing stuff  amazing 

有什么想法吗? 谢谢!

4 个答案:

答案 0 :(得分:5)

您可以这样做:

library(stringr)
library(dplyr)

dataframe %>%
  mutate(mymatch = sapply(str_extract_all(text, '\\w+'), 
                          function(x) x[nchar(x) == max(nchar(x))][1]))

使用purrr

library(purrr)

dataframe %>%
  mutate(mymatch = map_chr(str_extract_all(text, '\\w+'), 
                           ~ .[nchar(.) == max(nchar(.))][1]))

<强>结果:

# A tibble: 2 x 2
                   text mymatch
                  <chr>   <chr>
1 how is the biggest ?? biggest
2  really amazing stuff amazing

注意:

如果有平局,则需要第一个。

数据:

dataframe <- data_frame(text = c('how is the biggest ??',
                                 'really amazing biggest stuff'))

答案 1 :(得分:2)

一种简单的方法是将过程分解为两个步骤,首先是每行中所有单词列表的列表。然后找到并返回每个子列表中最长的单词:

df <- data_frame(text = c('how is the biggest ??',
                                 'really amazing stuff'))

library(stringr)
#create a list of all words per row
splits<-str_extract_all(df$text, '\\w+', simplify = FALSE)
#find longest word and return it
sapply(splits, function(x) {x[which.max(nchar(x))]})

答案 2 :(得分:2)

作为其他答案的变体,我建议编写一个执行操作的函数

longest_match <- function(x, pattern) {
    matches <- str_match_all(x, pattern)
    purrr::map_chr(matches, ~ .[which.max(nchar(.))])
}

然后使用它

dataframe %>%
    mutate(mymatch = longest_match(text, "\\w+"))

通过评论,似乎更好的做法是将longest_match()的新功能与mutate()启用的操作隔离开来。例如,该函数易于测试,可以在其他情况下使用,并且可以独立于数据转换步骤进行修改(“返回最后一次而不是第一次最长匹配”)。将所有内容都固定为一个没有实际价值line,所以编写逻辑上完成一件事的代码行是有意义的 - 找到所有匹配,从所有匹配映射到最长,... purrr::map_chr()优于sapply()因为它更健壮 - 它保证结果是一个字符向量,所以像

> df1 = dataframe[FALSE,]
> df1 %>% mutate(mymatch = longest_match(text, "\\w+"))
# A tibble: 0 x 2
# ... with 2 variables: text <chr>, mymatch <chr>

'做正确的事',即mymatch是一个字符向量(sapply()会在这种情况下返回一个列表。)

答案 3 :(得分:1)

或者,使用purrr ...

library(dplyr)
library(purrr)
library(stringr)

dataframe %>% mutate(mymatch=map_chr(str_extract_all(text,"\\w+"),
                                     ~.[which.max(nchar(.))]))

# A tibble: 2 x 2
  text                  mymatch
  <chr>                 <chr>  
1 how is the biggest ?? biggest
2 really amazing stuff  amazing