You can use purrr::map_depth to sort the nested lists, then check the lists with setdiff. If the length when you call setdiff is 0, the lists contain the same elements. The tricky thing is that setdiff will yield different results based on the order of its arguments, so you end up calling it twice, once from each direction. This is similar to the double checking done in testthat::expect_setequal.
For simplicity, I'm wrapping this in a function. You could instead do the same thing with a combination of all and %in%, but this seemed for compact.
a1 <- list("PL+", "PW-", "PL+", "PW-", c("PL+", "PW-"))
b1 <- list("PL+", c("PW-", "PL+"), "PL+", "PW-", "PW-")
nested_equal <- function(l1, l2) {
left_diff <- setdiff(
purrr::map_depth(l1, 1, sort),
purrr::map_depth(l2, 1, sort)
)
right_diff <- setdiff(
purrr::map_depth(l2, 1, sort),
purrr::map_depth(l1, 1, sort)
)
(length(left_diff) == 0) & (length(right_diff) == 0)
}
nested_equal(a1, b1)
#> [1] TRUE
A few test cases with different elements:
a2 <- list("PL+", "PW-", "PL+", "PW-", c("PL+", "PW-"), "A")
b2 <- list("PL+", c("PW-", "PL+"), "PL+", "PW-", "PW-")
nested_equal(a2, b2)
#> [1] FALSE
a3 <- list("PL+", "PW-", "PL+", "PW-", c("PL+", "PW-"))
b3 <- list("PL+", c("PW-", "PL+", "X"), "PL+", "PW-", "PW-", "B")
nested_equal(a3, b3)
#> [1] FALSE
To fit in with testthat tests, you could test against a true or false value returned by nested_equal in expect_equal, expect_true, expect_false.