我想用伪代码执行以下操作:
(a, b, c) = (HashSet(...), HashSet(...), HashSet(...))
(a, b, c) = (a - b - c, b - a - c, c - a - b)
在 Rust 中我尝试了这样的事情:
fn get_random_set(...) -> HashSet<String> {
...
}
// Sets of randomly generated "words" that define behavior of the whole program.
let action_plus: HashSet<String> = get_random_set();
let action_minus: HashSet<String> = get_random_set();
let action_new_line: HashSet<String> = get_random_set();
现在我们要从这些
HashSet
中排除所有常见的“单词”。
我了解到 difference
和 union
方法返回 Difference
和 Union
迭代器。如果我这样做:
let action_plus = HashSet::from(action_minus.union(&action_new_line).collect::<Vec<String>>());
我收到这个:
the trait `From<Vec<String>>` is not implemented for `HashSet<_, _>`
如何处理这个问题?
使用
impl FromIterator for HashSet直接收集到
HashSet
,而不是 Vec
。
即:
let action_plus: HashSet<_> = action_minus.union(&action_new_line).collect();
正如 Chayim 在评论中所说,您也可以使用
|
(BitOr
) 运算符,因为 HashSet
实现了它 并且正如文档所说:
返回 self 和 rhs 的并集作为新的 HashSet
如果您查看它的实现,您会发现它与上面的代码基本相同(尽管它从这些集合中克隆了项目):
impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>
where
T: Eq + Hash + Clone,
S: BuildHasher + Default,
{
type Output = HashSet<T, S>;
fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
self.union(rhs).cloned().collect()
}
}
HasSet
还实现了 BitAnd (&
) 运算符用于创建交集,Sub (-
) 用于创建集合差值和 BitXor (^
) 用于创建对称差值。
您可以使用这些便利运算符,但是当人们没有想到它们时,它们可能会令人反感,因此请小心使用它们。
您可以直接收集到
HashSet
。
let a = get_random_set();
let b = get_random_set();
let c = get_random_set();
let a_minus_b_minus_c = a
.difference(&b)
.cloned()
.collect::<HashSet<_>>()
.difference(&c)
.cloned()
.collect::<HashSet<_>>();
将输出从 cloned
转换为
HashSet<&String>
需要
HashSet<String>
,因为 difference
需要相同类型的集合。如果您同意 cloned
是 a_minus_b_minus_c
,则不需要最后一个 HashSet<&String>
。
但是,仅使用减法运算符会更容易。
HashSet
有 Sub
的实现,它通过引用获取两个操作数,因此每次都需要添加引用。
let a_minus_b_minus_c = &(&a - &b) - &c;
还有:
请注意,所有这些都会克隆集合中的值并返回一个新集合,因此它们的效率不是最佳的。如果您需要更高的性能,您可以通过使用
retain
(差异、交集)或 extend
(并集)修改第一个集合来手动执行操作,或者手动创建一个包含引用的新集合。