提问人:Some Name 提问时间:10/6/2020 最后编辑:mcartonSome Name 更新时间:10/16/2023 访问量:10977
检查 Vec 是否包含来自另一个 Vec 的所有元素
Check if Vec contains all elements from another Vec
答:
-4赞
Iulian Radu
10/6/2020
#1
您还可以对向量进行排序,然后测试它们的相等性:
fn main() {
let mut v1 = vec![2, 3, 1];
let mut v2 = vec![3, 1, 2];
v1.sort();
v2.sort();
assert_eq!(v1, v2);
}
评论
6赞
Masklinn
10/6/2020
请注意,他们问的是子集,而不仅仅是相等,例如 可能只是,但不是.v1
1
3
2
30赞
Peter Hall
10/6/2020
#2
您有两个主要选择:
天真地检查一个向量中的每个元素,看看它是否在另一个向量中。这具有时间复杂度 O(n^2),但它也非常简单且开销低:
assert!(b.iter().all(|item| a.contains(item)));
创建一个包含其中一个向量的所有元素的集合,然后检查另一个向量的元素是否包含在其中。这具有 O(n) 时间复杂度,但开销更高,包括额外的堆分配:
let a_set: HashSet<_> = a.iter().copied().collect(); assert!(b.iter().all(|item| a_set.contains(item)));
哪一个“更好”将取决于您的要求。如果你只关心速度,更好的选择仍然取决于向量中的元素数量,所以你应该用真实的数据来测试两者。您还可以使用 进行测试,它具有与 不同的性能特征。BTreeSet
HashSet
以下是一些粗略的基准(来源),说明实现如何随输入大小而变化。在所有测试中,大小是 的一半,并且包含 元素的随机子集:b
a
a
尺寸a |
Vec::contains |
HashSet::contains |
BtreeSet::contains |
---|---|---|---|
10 | 14 | 386 | 327 |
100 | 1,754 | 3,187 | 5,371 |
1000 | 112,306 | 31,233 | 88,340 |
10000 | 2,821,867 | 254,801 | 728,268 |
100000 | 29,207,999 | 2,645,703 | 6,611,666 |
以纳秒为单位的时间。
当元素数量较少时,朴素解速度最快。当大小大于约 200 时,分配 or 的开销会因比较次数的影响而黯然失色。 大多比 慢很多,但在元素数量非常少时略快。O(n^2)
HashSet
BTreeSet
BTreeSet
HashSet
1赞
x1hgg1x
7/2/2021
#3
如果你有排序的向量,你可以在线性时间内进行搜索:
let mut vec = vec![0, 2, 4, 3, 6, 3, 5, 1, 0];
let mut v = vec![1, 4, 3, 3, 1];
vec.sort_unstable();
v.sort_unstable();
// Remove duplicates elements in v
v.dedup();
let mut vec_iter = vec.iter();
assert!(v.iter().all(|&x| vec_iter.any(|&item| item == x)));
参考:C++ 具有 std::include,它正是这样做的。
评论
0赞
Peter Hall
7/30/2021
如果有重复的元素,这将给出不正确的结果 - 或者至少是不同的结果。如果要求另一个 vec 包含相同数量的每个项目,则这是正确的。v
0赞
x1hgg1x
7/31/2021
我已经编辑了我的答案以处理 中重复元素的情况。v
0赞
Dudeguy
10/16/2023
#4
在这里补充其他答案:根据你的设置方式,你可以通过比较它们的长度来节省一些比较。只有当 vec 的长度大于或等于 's 时,vec 才能包含(并且没有重复项。Vec
a
b
b
b
assert!(a.len() >= b.len());
评论
other_vector.iter().all(|e| vector.contains(e))
似乎还不错。