Matt
Matt

Reputation: 83

R: Cross reference vector with list, HELP: append new vector based on positive hits

I have a vector A and a list B of vectors v1, v2 and v3. I aim to combine the vectors in list B that contain one or more of the entries of A into a new vector (new_v).

A <- c("cat", "dog", "bird")
A

B <- list(v1 = c("mike", "fred", "paul"), v2 = c("mouse", "cat", "frog"), v3 = c("bird", "cow", "snake"))
B

new_list <- c()

for(i in names(B)){       
  
  v <- A %in% B[[i]]            ## test for elements of A in vectors of B
  print(v)
  
  if (TRUE %in% v){             ## if TRUE (A is in vector of B), 
                                ## add vector of B to new_v 
    
    append(new_v, unlist(B[i])) ## doesn't do what I want
    
  }
}
dput(new_v)

The result I was hoping for:

>dput(new_v)
c("mouse", "cat", "frog", "bird", "cow", "snake")

Upvotes: 1

Views: 87

Answers (2)

Rui Barradas
Rui Barradas

Reputation: 76460

Here is a one-liner with Map.

unlist(Map(function(x, y) {if(any(x %in% y)) y}, list(A), B))
#[1] "mouse" "cat"   "frog"  "bird"  "cow"   "snake"

Explanation:

Map applies the anonymous function to every element of its list arguments. Since list(A) has length 1, it is recycled to the length of the list B.
As for the function, if any element of x, (the vector A) is in y (each of the vectors of B) then y is returned, else NULL is returned.

Edit

If B has a dim attribute set, then it can be an object of class "matrix" or of class "data.frame" (or inheriting from one of those classes).

1. If it is a matrix, coerce to vector and there is no need for Map.

if(any(A %in% as.vector(B))) B
#     [,1]    [,2]              
#[1,] "mouse" "mice eat rats"   
#[2,] "cat"   "cats eat mice"   
#[3,] "frog"  "frogs frog frogs"

2. If it is a data.frame, unlist where it's as.vector above.

B2 <- as.data.frame(B)
if(any(A %in% unlist(B2))) B2
#     V1               V2
#1 mouse    mice eat rats
#2   cat    cats eat mice
#3  frog frogs frog frogs
 

Upvotes: 2

akrun
akrun

Reputation: 887241

Another option is map2 from purrr

library(purrr)
map2(list(A), B, ~ if(any(.x %in% .y)) .y) %>%
    flatten_chr
#[1] "mouse" "cat"   "frog"  "bird"  "cow"   "snake"

Upvotes: 1

Related Questions