Функция, эквивалентная stringr::word в пакете stringi

Я просмотрел руководство по пакету stringi, чтобы найти эквивалент функции word() в пакете stringr, но не смог его найти. Причина, по которой я ищу его, заключается в том, что я хочу установить параметры сортировки для моей локали, а stringr не дает мне всех параметров, которые дает stringi. Есть ли в пакете stringi функция, которая делает то же самое, что и функция word() в пакете stringr? См. пример ниже, где я хочу, чтобы следующие три слова после слова «Хосе» писались по-разному. В пакете stringi функция stri_opts_collatorпозволяет установить аргумент strength=1 для разрешающей силы сортировки, чтобы учитывались все формы "Хосе".

sentencas<-c("josé é um trabalhador responsável","José é um trabalhador 
responsável","jose é um trabalhador responsável","Jose é um trabalhador 
responsável")

sentencas %>% word(2,sep=coll("jose ",ignore_case=T)) %>% word(1,3)

С помощью stringi я могу извлечь все формы «Хосе»:

stri_extract_first_coll(sentencas,"jose",strength=1).

Я хотел бы сделать что-то вроде этого:

sentencas %>% word(2,sep=coll("jose ",strength=1)) %>% word(1,3)

person José    schedule 13.11.2017    source источник


Ответы (3)


Не совсем то же самое, что и stringr::word(), но, похоже, это поможет:

sentencas %>% 
  stri_split_coll("jose ", strength=1, simplify = TRUE) %>% 
  .[,2] %>% 
  word(1,3)
person David Klotz    schedule 13.11.2017

Вот еще вариант. Обратите внимание, что я ввел несколько слов перед вашим словом-маркером для извлечения, например, «Хозе», так как я предполагаю, что у вас будут не только предложения, начинающиеся с этого слова. Важной функциональностью является комбинация использования stri_locate для определения конца слова-маркера, добавления одной позиции символа и использования этой позиции с последней позицией символа в вашей строке, которая будет передана в stri_sub. Обратите внимание, что предоставленная функция не является отказоустойчивой, например, для случаев, когда нет совпадений и т. д.

Пожалуйста, также проверьте приведенные ниже тесты для трех предложенных решений.

library(stringi)
library(magrittr)

sentencas<- c("some words josé é um trabalhador responsável"
              ,"only one word José é um trabalhador responsável"
             ,"several words jose é um trabalhador responsável"
             ,"and again some words Jose é um trabalhador responsável")

stri_word <- function(marker, str, words_after_marker) {

  stri_sub(str,  cbind(stri_locate_first_coll(str, marker ,strength=1)[, "end"]+1, nchar(str)) ) %>% 
  { gsub( "^\\s+|\\s+$", "", stri_extract_first_regex(., paste0("(\\s\\w+){", words_after_marker[1], ",", words_after_marker[2],"}"))) }

}

stri_word("jose", sentencas, c(1,3) )

#[1] "é um trabalhador" "é um trabalhador" "é um trabalhador" "é um trabalhador"

#Benchmarks
library(microbenchmark)
library(stringr)

stringi_positions <- function() {

  stri_word <- function(marker, str, words_after_marker) {

    stri_sub(str,  cbind(stri_locate_first_coll(str, marker ,strength=1)[, "end"]+1, nchar(str)) ) %>%
    { gsub( "^\\s+|\\s+$", "", stri_extract_first_regex(., paste0("(\\s\\w+){", words_after_marker[1], ",", words_after_marker[2],"}"))) }

  }

  stri_word("jose", sentencas, c(1,3) )


}

stringi_map <- function() {

  sentencas %>%
    map(stri_extract_all_words) %>% 
    map(~{
      .x <- flatten_chr(.x)
      map(.x, stri_detect_coll, "jose", ignore.case=TRUE, strength=1L) %>% 
        flatten_lgl() %>%
        which() -> pos
      .x[(pos+1):(pos+1+3)]
    })


}


semi_stringi <- function() {

  sentencas %>% 
    stri_split_coll("jose ", strength=1, simplify = TRUE) %>% 
    .[,2] %>% 
    word(1,3)


}


microbenchmark(
  stringi_map(),
  semi_stringi(),
  stringi_positions()
)

# Unit: microseconds
#                        expr      min       lq      mean    median        uq       max neval
# stringi_map()       3498.667 3752.886 4059.0339 4038.0925 4214.3480  7365.635   100
# semi_stringi()      485.543  558.966  805.0216  593.9015  652.7195 15806.567   100
# stringi_positions()  288.958  325.669  456.9946  344.6180  384.4865 10719.428   100
person Manuel Bickel    schedule 13.11.2017

word() — довольно сложная функция, и в stringi нет ни одной эквивалентной функции. Это еще один способ добиться желаемых результатов:

library(stringi)
library(purrr)

sentencas <- c("josé é um trabalhador responsável",
               "José é um trabalhador responsável",
               "jose é um trabalhador responsável",
               "Jose é um trabalhador responsável")

sentencas %>%
  map(stri_extract_all_words) %>% 
  map(~{
    .x <- flatten_chr(.x)
    map(.x, stri_detect_coll, "jose", ignore.case=TRUE, strength=1L) %>% 
      flatten_lgl() %>%
      which() -> pos
    .x[(pos+1):(pos+1+3)]
  })
## [[1]]
## [1] "é"           "um"          "trabalhador" 
## 
## [[2]]
## [1] "é"           "um"          "trabalhador"
## 
## [[3]]
## [1] "é"           "um"          "trabalhador" 
## 
## [[4]]
## [1] "é"           "um"          "trabalhador" 
person hrbrmstr    schedule 13.11.2017