#r
#r
Вопрос:
Я ищу метод разделения символьного вектора на основе шаблона регулярных выражений.
Пример ввода:
input <- c("a_foo","b_foo", "c_bar", "d_bar")
split_by <- c("foo", "bar")
Результат, который я ищу:
$foo
[1] "a_foo" "b_foo"
$bar
[1] "c_bar" "d_bar"
Редактировать
Основываясь на комментариях и ответах, необходимо внести некоторые уточнения.
split_by
может содержать любое количество элементов;- шаблон регулярных выражений варьируется от случая к случаю; и
- элементу в
input
может быть присвоено значение 0 (совпадений нет), 1 или несколько разделений в зависимости от совпадения.
Следовательно, следующий ввод:
input <- c("foo_bar", "nothing", "a_foo", "c_bar")
split_by <- c("foo", "bar")
Мог бы вернуться:
$foo
[1] "foo_bar" "a_foo"
$bar
[1] "foo_bar" "c_bar"
Комментарии:
1. Может
split_by
содержать более 2 элементов?2. @sindri_baldur Пожалуйста, ознакомьтесь с обновленным вопросом.
Ответ №1:
В реальном случае вы можете извлекать split_by
значения из input
данных?
Это работает для общего примера.
split(input, sub('.*_', '', input))
#$bar
#[1] "c_bar" "d_bar"
#$foo
#[1] "a_foo" "b_foo"
где
sub('.*_', '', input) #returns
#[1] "foo" "foo" "bar" "bar"
Ответ №2:
lapply(split_by, grep, x = input, value = TRUE)
# [[1]]
# [1] "a_foo" "b_foo"
#
# [[2]]
# [1] "c_bar" "d_bar"
Чтобы получить именованный вывод, вы могли бы сделать:
lapply(setNames(split_by, split_by), grep, x = input, value = TRUE)
Ответ №3:
split.regex <- function(input, split_by, pattern, add_names=TRUE) {
out <- lapply(split_by, function(x) {
input[grepl(sprintf(pattern, x), input)]
})
if (add_names) {
names(out) <- split_by
}
return(out)
}
Во-первых, необходимо определить шаблон. Поскольку foo
и bar
встречается в конце строки, sprintf("%s$", split_by)
может быть использован. В функции я определил sprintf
внутреннюю часть функции, поэтому аргумент pattern
должен быть определен как sprintf
строка "%s$"
.
Первый пример
Определив input
и split_by
, как в первом примере вопроса, а затем запустив:
split.regex(input=input, split_by=split_by, pattern="%s$", add_names=TRUE)
Мы получаем желаемый результат:
$foo
[1] "a_foo" "b_foo"
$bar
[1] "c_bar" "d_bar"
Второй пример
Определив input
и split_by
, как во втором примере вопроса, а затем запустив:
split.regex(input=input, split_by=split_by, pattern="(%s)", add_names=TRUE)
Мы получаем желаемый результат:
$foo
[1] "foo_bar" "a_foo"
$bar
[1] "foo_bar" "c_bar"
Поскольку входные "nothing"
данные не совпадали ни с одним, они были правильно исключены из разделения, тогда "foo_bar"
как были правильно добавлены к обоим разделениям, поскольку они совпадали на обоих.