Разделить определенные строки в векторе с помощью регулярного выражения

У меня есть вектор строк, некоторые из которых содержат знаки препинания/символы. Например:

words <- ("hi", "my.", "name!", "is98", ""joe"")

Моя цель — создать вектор, в котором есть все эти слова, но знаки препинания, числа и символы превращаются в собственную строку в векторе. Итак, в этом случае

("hi", "my", ".", "name", "!", "is", "98", """, "joe", """)

Мой первоначальный план состоял в том, чтобы использовать grep для определения индексов, в которых существуют указанные знаки препинания, затем пройтись по ним и использовать strsplit для их разделения на основе указанных знаков препинания следующим образом:

puncIndex <- grep('[\\"!?.^]', words)
for(i in puncIndex){
  strsplit(words[i], '[\\"!?.^]')
}

Но у меня есть пара проблем. Во-первых, я понимаю, что результатом strsplit будет сам список, и я не могу понять, как аккуратно просто переместить каждый из компонентов обратно в исходный вектор. Другое дело, что даже когда я пробую strsplit только для одного слова, возвращается только первая часть. Например:

strsplit(words[2], ".")
[[1]]
[1] "my"

РЕДАКТИРОВАТЬ: добавлены числа как класс, который также нужно разделить


person NeonBlueHair    schedule 09.07.2015    source источник


Ответы (2)


Просто разделите границу слова, которая существует посередине.

words <- c("hi", "my.", "name!", "is", '"joe"')
unlist(strsplit(words, '(?<=.)\\b(?=.)', perl=TRUE))
#[1] "hi"   "my"   "."    "name" "!"    "is"   "\""   "joe" 
#[9] "\"" 

Хитрость здесь заключается в том, что \\b называется границей слова, которая соответствует слову char и не слову char (наоборот). Так что это само по себе будет соответствовать началу и концу, если начальный и конечный символ является символом слова. Но с помощью утверждений он гарантирует, что до и после границы слова должен существовать хотя бы один символ.

Обновление:

library(stringr)
unlist(str_extract_all(words, '[A-Za-z]+|[^A-Za-z]+'))
person Avinash Raj    schedule 09.07.2015
comment
Спасибо, это тоже сработало! Есть ли разница в производительности между использованием \b и использованием \w, как и в другом предложенном ответе? - person NeonBlueHair; 10.07.2015
comment
Извините, я должен был лучше сформулировать свой вопрос. Я имел в виду больше, какая будет разница в выводе, учитывая, что я попробовал оба, и они оба дали одинаковый результат. Но, прочитав ваше объяснение еще раз, я думаю, что понял его. Спасибо! - person NeonBlueHair; 10.07.2015

Вы можете попробовать

  res <- unlist(strsplit(words, '(?<=\\w)(?=\\W)|(?<=\\W)(?=\\w)',
                   perl=TRUE))
  res
  #[1] "hi"   "my"   "."    "name" "!"    "is"   "\""   "joe"  "\""  

Или используя str_extract_all

 library(stringr)
 unlist(str_extract_all(words, '\\w+|\\W+'))
 #[1] "hi"   "my"   "."    "name" "!"    "is"   "\""   "joe"  "\""  

РЕДАКТИРОВАТЬ: добавлено предложение @Avinash Raj

данные

 words <- c("hi", "my.", "name!", "is", '"joe"')
person akrun    schedule 09.07.2015
comment
Спасибо, первое решение сработало идеально. Еще один вопрос (извините, что забыл спросить сначала): как бы я изменил его на отдельные числа? - person NeonBlueHair; 10.07.2015
comment
@NeonBlueHair Пожалуйста, обновите свой пост новым примером, в котором также есть числа. - person akrun; 10.07.2015