'How to compare two lists in R
I have two lists that I want to compare. I want to see if the values of each element of the list are equal or not.
> m1
[[1]]
integer(0)
[[2]]
[1] 3 4
[[3]]
integer(0)
[[4]]
[1] 1
[[5]]
[1] 2 3 4
> m3
[[1]]
[1] 3
[[2]]
[1] 1 4
[[3]]
[1] 2
[[4]]
[1] 3
[[5]]
[1] 1 4
And I expect a result like this:
> Result
[[1]]
[1]
FALSE
[[2]]
[1]
FALSE TRUE
[[3]]
[1]
FALSE
[[4]]
[1]
FALSE
[[5]]
[1]
FALSE FALSE TRUE
If I try to apply m1[1]==m3[1] or similar, I get messages as Error in m1 == m3 : comparison of these types is not implemented. I don't manage to do that simple thing! Thanks for your help in advance.
Solution 1:[1]
You can use Map(or mapply) with %in%.
Map(`%in%`, m1, m3)
[[1]]
logical(0)
[[2]]
[1] FALSE TRUE
[[3]]
logical(0)
[[4]]
[1] FALSE
[[5]]
[1] FALSE FALSE TRUE
However, m1 contains integer(0), which makes %in% return logical(0) instead of FALSE. So you need to convert logical(0) to FALSE afterward.
res <- Map(`%in%`, m1, m3)
res[lengths(res) == 0] <- FALSE
res
[[1]]
[1] FALSE
[[2]]
[1] FALSE TRUE
[[3]]
[1] FALSE
[[4]]
[1] FALSE
[[5]]
[1] FALSE FALSE TRUE
Solution 2:[2]
You can try using the purrr library to get your desired output, that examines each element. I used %in% instead of == if NAs exist. Also this assumes each list has the same structure to work.
library(purrr)
purrr::map2(m1, m3, function(x, y) x %in% y)
Solution 3:[3]
Both Darren and EJJ decided to go along and use %*%
If we don't mind the default behaviour of NA in boolean comparison, we can use a simple for-loop or lapply
lapply(seq(la), function(i)a[[i]] == b[[i]])
If we want some security that the lists are 'matchable' we can compare their outer and inner lengths and wrap this in a function as below
compare_each_list_element <- function(a, b){
la <- length(lla <- lengths(a))
lb <- length(llb <- lengths(b))
if(la != lb || any(lla != llb)){
warning('Either length(a) != length(b) or some length within a is not equal to some length within b!')
return(FALSE)
}
lapply(seq(la), function(i)a[[i]] == b[[i]])
}
compare_each_list_element(list(1:3, 2, c(3, 2)), list(1:3, 3, c(2, NA)))
[[1]]
[1] TRUE TRUE TRUE
[[2]]
[1] FALSE
[[3]]
[1] FALSE NA
Solution 4:[4]
The compare() function in {waldo} makes it very easy to compare lists or data frames. In this case:
m1 = list(integer(), c(3,4), integer(), 1, c(2, 3, 4))
m3 = list(3, c(1,4), 2, 3, c(1, 4))
waldo::compare(m1, m3, x_arg = "m1", y_arg = "m3")
#> `m1[[1]]` is an integer vector ()
#> `m3[[1]]` is a double vector (3)
#>
#> `m1[[2]]`: 3 4
#> `m3[[2]]`: 1 4
#>
#> `m1[[3]]` is an integer vector ()
#> `m3[[3]]` is a double vector (2)
#>
#> `m1[[4]]`: 1
#> `m3[[4]]`: 3
#>
#> `m1[[5]]`: 2 3 4
#> `m3[[5]]`: 1 4
The console output is color coded:
Created on 2022-03-16 by the reprex package (v2.0.1)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | EJJ |
| Solution 3 | Oliver |
| Solution 4 | Gorka |

