Функция для поиска общих элементов 2 списков в R, без использования ‘intersect’

#r

#r

Вопрос:

Я пытаюсь использовать R для создания функции, которая принимает два списка в качестве входных данных и возвращает общие элементы, но без использования функции intersect. Я все еще борюсь с некоторыми вещами, когда изучаю R:

  • списки против векторов против фреймов данных
  • как сохранить / сохранить результаты из циклов и функций for
  • как использовать sapply / mapply / etc.

Вот что у меня есть на данный момент. Сначала я думал, что это сработало, когда единственным общим элементом было ‘5’, но когда я добавил более общие числа, он по-прежнему возвращает только ‘5’.

** Примечание — после написания этого я понял, что необходимо запускать это только в одном направлении (есть ли что-нибудь в list_a также в list_b), но теперь мне любопытно, как запустить эту версию с точки зрения программирования.


 a <- list(1,2,3,4,5)
b <- list(3,4,5,6,7,8,9,10,11)

a_match <- numeric()
b_match <- numeric()

ab <- function(list_a, list_b) {
  for (i in list_a) {
    results <- if(i %in% list_b) {i}
    a_in_b <- c(a_match, results)
  }
  for (i in list_b) {
    results <- if(i %in% list_a) {i}
    b_in_a <- c(b_match, results)
  }
  combined <- c(a_in_b, b_in_a)
  unique(combined)
}


ab(a, b)
  

Есть ли способ использовать ‘apply’ здесь? и:

  1. возвращает вектор, длина которого отличается от длины входных данных (ограничение sapply)
  2. может принимать несколько входных данных разной длины (ограничение отображения)

Комментарии:

1. вы имеете дело с наборами?? например a<- list(3, 4, list(1,2) , и b<- list(4, list(2,1), 3) будете ли вы считать эти два эквивалентными?? по умолчанию они

Ответ №1:

Ваши a_match и b_match находятся вне объявленных вне функции. Я исправил ваш пример проверки ниже:

 a <- list(1,2,3,4,5)
b <- list(3,4,5,6,7,8,9,10,11)

ab <- function(list_a, list_b) {
  
  a_match <- numeric()
  b_match <- numeric()

  
  for (i in list_a) {
    results <- if(i %in% list_b) {i}
    a_match <- c(a_match, results)
  }
  
  for (i in list_b) {
    results <- if(i %in% list_a) {i}

    b_match <- c(b_match, results)
  }
  combined <- c(a_match,b_match)
  
  unique(combined)
}


ab(a, b)
  

Комментарии:

1. Большое вам спасибо! Почему для R имеет значение, объявлены ли они внутри или вне функции?

2. @kwsunshine123 Это связано с областью видимости. Все переменные внутри функции должны быть объявлены внутри функции или должны быть переданы в качестве параметра в функцию.

Ответ №2:

мы могли бы просто использовать %in% функцию для получения элементов, которые находятся в a и b => a %in% b является логическим вектором, который мы используем для подмножества исходного списка.

 a %in% b
#> [1] FALSE FALSE  TRUE  TRUE  TRUE
unique(a[a %in% b])
  
 [[1]]
[1] 3

[[2]]
[1] 4

[[3]]
[1] 5
  

Имейте в виду, что большинство операторов (функций) в базовом векторизованы, поэтому нет необходимости использовать семейство apply в этом.

 unlist(unique(a[a %in% b]))
#> [1] 3 4 5
  

Комментарии:

1. Спасибо!! Я действительно борюсь с тем, насколько запутан вывод списка (я предполагаю, что вывод, который вы напечатали, представляет собой список). Почему он просто не возвращает аккуратный вектор, соответствующий вводу?

2. @kwsunshine123 поскольку мы задаем подмножество списка, если вы хотите, чтобы он возвращал вектор, оберните его в unlist вызов. одна вещь, которая важна в программировании на R, — это использование векторизованного аспекта, поскольку он оптимизирован больше, чем для циклов, и эстетически лучше. Также обратите внимание, что это работает даже для дочерних списков, которые находятся в a и b

3. @kwsunshine123 обратите внимание, что если вы хотите, чтобы a и b были вложенными списками, добавьте recursive=FALSE к вызову unlist