提问人:nalzok 提问时间:7/10/2019 更新时间:7/10/2019 访问量:762
如何测试列表是否相等而不考虑顺序?
How to test for list equality regardless of order?
问:
我正在使用 testthat 框架,但这个问题应该适合更大的背景。基本上,我有一个输出这个的函数
list("PL+", "PW-", "PL+", "PW-", c("PL+", "PW-"))
但是,我不在乎订单,所以这也完全没问题
list("PL+", c("PW-", "PL+"), "PL+", "PW-", "PW-")
如何测试是否相等?我正在考虑后跟一个 ,但这会破坏嵌套结构。expect_equal
unlist
sort
答:
1赞
camille
7/10/2019
#1
您可以使用对嵌套列表进行排序,然后使用 .如果调用时的长度为 0,则列表包含相同的元素。棘手的是,它会根据其参数的顺序产生不同的结果,因此您最终会调用它两次,每个方向一次。这类似于 中执行的双重检查。purrr::map_depth
setdiff
setdiff
setdiff
testthat::expect_setequal
为简单起见,我将其包装在一个函数中。相反,您可以使用 和 的组合来执行相同的操作,但这似乎是紧凑的。all
%in%
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
一些具有不同元素的测试用例:
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
为了适应测试,您可以针对 、 、 返回的 true 或 false 值进行测试。testthat
nested_equal
expect_equal
expect_true
expect_false
2赞
Cole
7/10/2019
#2
sort()
并且可能是最好的选择。unlist()
identical(sort(unlist(a1)), sort(unlist(b1)))
你对打破嵌套结构表示犹豫,但请注意它不是永久性的。您仍然可以毫无问题地访问任一列表。sort(unlist(...))
此外,虽然我不熟悉该包,或者应该提供类似的结果,但如果它们相等,则该语句会静默执行。testthat
expect_equal
expect_identical
> identical(sort(unlist(a1)), sort(unlist(b1)))
[1] TRUE
> a1
[[1]]
[1] "PL+"
[[2]]
[1] "PW-"
[[3]]
[1] "PL+"
[[4]]
[1] "PW-"
[[5]]
[1] "PL+" "PW-"
数据 h/t 到@camille数据。
a1 <- list("PL+", "PW-", "PL+", "PW-", c("PL+", "PW-"))
b1 <- list("PL+", c("PW-", "PL+"), "PL+", "PW-", "PW-")
0赞
d.b
7/10/2019
#3
遍历列表的元素并相互检查
l1 = list("PL+", "PW-", "PL+", "PW-", c("PL+", "PW-"))
l2 = list("PL+", c("PW-", "PL+"), "PL+", "PW-", "PW-")
temp = sapply(l1, function(x) sapply(l2, function(y) identical(sort(x), sort(y))))
all(rowSums(temp) > 0) & all(colSums(temp) > 0)
#[1] TRUE
评论