Mrygh
Mrygh

Reputation: 27

How to remove elements in a list by a sublist?

I have two list a and another sub list which is b:

a <- list(c("aa","bb","cc"), c("a","b","c","d","e"))
b <- list(c("aa","cc"),c("a","b","c")) 

I'd like to extract b from a and result should looks like

list(c("bb"), c("d","e")

I have tried:

1) Map(`[`, a, b)

2) map2(a, b, `[`)

3) sapply(names(a), function(x) a[[x]][,b[[x]], drop = FALSE])

But non of them works. I appreciate your help and support.

Upvotes: 1

Views: 122

Answers (2)

arg0naut91
arg0naut91

Reputation: 14764

Try:

Map(function(x, y) x[!x %in% y], a, b)

[[1]]
[1] "bb"

[[2]]
[1] "d" "e"

Upvotes: 0

akrun
akrun

Reputation: 887391

An option would be to use setdiff with Map

Map(setdiff, a, b)
#[[1]]
#[1] "bb"

#[[2]]
#[1] "d" "e"

Or the similar option in map2

library(purrr)
map2(a, b, setdiff)

Regarding the use of names to loop, if we check the names(a) or names(b), it is NULL

names(a)
#NULL

because the names were not set. When creating the list, it can be done with

a1 <- list(v1 = c("aa","bb","cc"), v2 = c("a","b","c","d","e"))

or after the list is created. can set the names with

names(a1) <- c("v1", "v2")

or while creating the list, use setNames

a1 <- setNames(list(c("aa","bb","cc"), c("a","b","c","d","e")), c("v1", "v2"))

if the names are NULL, looping through NULL will fail anyway. An option that is more better is to loop through the numeric index or sequence of list. We don't have to worry about whether the names are set or not.

lapply(seq_along(a), function(i) setdiff(a[[i]], b[[i]]))

Upvotes: 2

Related Questions