Разделенный вектор, классифицированный по регулярному выражению

#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"
 

Редактировать

Основываясь на комментариях и ответах, необходимо внести некоторые уточнения.

  1. split_by может содержать любое количество элементов;
  2. шаблон регулярных выражений варьируется от случая к случаю; и
  3. элементу в 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" как были правильно добавлены к обоим разделениям, поскольку они совпадали на обоих.