【问题标题】:"Popping" a value from a HashSet从 HashSet 中“弹出”一个值
【发布时间】:2021-08-18 00:06:17
【问题描述】:

我似乎找不到从HashSet 中弹出(随机)值的方法。受其他代码示例的启发,我编写了以下代码:

my_set.iter().next().map(|i| my_set.take(i).unwrap())

即获取集合值的迭代器,从中获取第一个值(引用),然后使用先前获得的引用运行my_set.take(),以获取值本身(不是引用)并将其从设置。

由于以下原因无法编译:

error[E0500]: closure requires unique access to `my_set` but it is already borrowed
   |
32 |         my_set.iter().next().map(|i| my_set.take(i).unwrap())
   |         ------               --- ^^^ ------ second borrow occurs due to use of `my_set` in closure
   |         |                    |   |
   |         |                    |   closure construction occurs here
   |         |                    first borrow later used by call
   |         borrow occurs here

我已经尝试了很多很多变体,但由于不可变借用然后被借用为可变(错误 502),它们都失败了。

任何人都可以推荐一种重写上述方法的方法吗?

【问题讨论】:

标签: rust hashset borrow-checker


【解决方案1】:

如果您可以克隆删除的项目,您可以这样做:

let elem = set.iter().next().unwrap().clone();
set.remove(&elem);

Playground

或者防止集合为空:

if let Some(elem) = set.iter().next().cloned() {
    set.remove(&elem);
}

Playground

【讨论】:

  • 谢谢。是的,这行得通……但我很好奇:有没有更优雅的方法不需要克隆?
  • @Maan hashset from std is lost 我不知道为什么我建议直接使用 hashmap 或使用一些 crate
【解决方案2】:

这感觉很hacky,但您可以将HashSet::retain 与不纯函数一起使用:

let mut flag = false;
my_set.retain(|_| mem::replace(&mut flag, true));

(playground)

删除的元素确实是任意的——我在操场上运行了几次代码,得到了不同的结果。


正如 comment 中提到的 interjay,这种方法迭代整个集合只是为了删除一个值,因此成本通常比克隆一个值更重要。因此,仅当元素确实无法克隆时才使用此解决方法。

【讨论】:

  • 这将遍历整个集合以删除一个值。
猜你喜欢
  • 1970-01-01
  • 2015-11-16
  • 2021-12-08
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-14
相关资源
最近更新 更多