- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想从 BTreeMap
中删除通过迭代找到的项目。
由于无法在迭代时删除项目,我将要删除的项目放入一个向量中。主要问题是不可能使用引用 向量,而只能使用值向量。然后必须克隆所有必须删除条目的 key (假设 key 实现了 Clone
特性)。
例如,这个简短的示例无法编译:
use std::collections::BTreeMap;
pub fn clean() {
let mut map = BTreeMap::<String, i32>::new();
let mut to_delete = Vec::new();
{
for (k, v) in map.iter() {
if *v > 10 {
to_delete.push(k);
}
}
}
for k in to_delete.drain(..) {
map.remove(k);
}
}
fn main() {}
编译时会产生如下错误:
error[E0502]: cannot borrow `map` as mutable because it is also borrowed as immutable
--> src/main.rs:17:9
|
9 | for (k, v) in map.iter() {
| --- immutable borrow occurs here
...
17 | map.remove(k);
| ^^^ mutable borrow occurs here
18 | }
19 | }
| - immutable borrow ends here
将 to_delete.push(k)
更改为 to_delete.push(k.clone())
可使此代码段正确编译,但如果要删除每个键,成本会很高必须克隆。
有没有更好的解决方案?
最佳答案
TL;DR:你不能。
就编译器而言,执行BTreeMap::remove
可能会这样做:
pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: Ord + ?Sized,
{
// actual deleting code, which destroys the value in the set
// now what `value` pointed to is gone and `value` points to invalid memory
// And now we access that memory, causing undefined behavior
key.borrow();
}
因此,当集合发生变化时,编译器必须阻止使用对值的引用。
为此,您需要类似假设的集合“游标”API 之类的东西。这将允许您遍历集合,返回一个特殊类型来保存集合的可变内部结构。这种类型可以为您提供引用以进行检查,然后允许您删除该项目。
我可能会从不同的角度看待这个问题。我不想保留 map ,而是创建一个全新的 map :
use std::collections::BTreeMap;
pub fn main() {
let mut map = BTreeMap::new();
map.insert("thief", 5);
map.insert("troll", 52);
map.insert("gnome", 7);
let map: BTreeMap<_, _> =
map.into_iter()
.filter(|&(_, v)| v <= 10)
.collect();
println!("{:?}", map); // troll is gone
}
如果您的条件在使结构唯一的字段上相等(也就是 PartialEq
和 Hash
中使用的唯一字段),您可以为您的类型实现 Borrow
并直接抓取它/删除它:
use std::collections::BTreeMap;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Monster(String);
use std::borrow::Borrow;
impl Borrow<str> for Monster {
fn borrow(&self) -> &str { &self.0 }
}
pub fn main() {
let mut map = BTreeMap::new();
map.insert(Monster("thief".into()), 5);
map.insert(Monster("troll".into()), 52);
map.insert(Monster("gnome".into()), 7);
map.remove("troll");
println!("{:?}", map); // troll is gone
}
另见:
关于rust - 从通过迭代找到的 BTreeMap 或 BTreeSet 中删除项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32913368/
有没有办法加入BTreeSet在使用空格的同时使用它来获取每个元素由空格分隔的字符串,而不是通过遍历每个元素并推送到一个字符串? 我的集合可能非常大,最多可能有 10GB,所以我想限制内存使用量。 t
我有一个集合,它是某个模块中结构中的一个字段。我想从另一个模块更新集合中的所有值。 我写了一些代码来模仿我想要实现的目标。它缩短了一点,但我认为它具有所有需要的部分。这段代码中没有保存集合的结构,但可
我想修改 BTreeSet 中的结构。 我想实现类似以下的东西 here : use std::collections::BTreeSet; #[derive(Eq, PartialEq, Ord,
在 Rust 中,我有一个 BTreeSet,我用它来保持我的值有序。我有一个循环,应该检索并删除集合的第一个(最低)成员。我正在使用克隆的迭代器来检索第一个成员。这是代码: use std::col
我有一个 BTreeSet并且需要小于给定元素的最大元素。看起来我会使用类似的东西: let set: BTreeSet = ...; let e: T = ...; let result = e.r
我希望能够在 Rust BTreeSet 中找到严格小于和大于指定键的键。 例如,给定集合 { "1", "3"},搜索关键字是 "2" 那么答案应该是 ( “1”,“3”)。在不存在更低或更高值的情
阅读 BTreeSet 文档,我似乎无法弄清楚如何从 BTreeSet 中获取大于元素的最小值或小于元素的最大值对数时间。 我看到有一个 range可以在任意(最小值、最大值)范围内给出值的方法,但是
在C++中,可以自定义代码std::set用于对其参数进行排序。默认情况下它使用 std::less , 但这可以用 Compare 改变模板参数。 Rust 的 BTreeSet使用 Ord对类型进
我不确定这是否是一个新手问题。 rust 标准库 std::collections提供 map 和 set 的 B-tree 实现。 我查看了文档 here ,但我找不到用于实现的分支因子 m。 最佳
如果我对 B 树的理解正确,那么在对数时间内搜索 key 应该是容易且可能的。如果key不存在,返回下一个更小更大的key;给定键的邻居,如果它会被插入。 这个功能是否已经存在? 使用当前 API 的
我想从 BTreeMap 中删除通过迭代找到的项目。 由于无法在迭代时删除项目,我将要删除的项目放入一个向量中。主要问题是不可能使用引用 向量,而只能使用值向量。然后必须克隆所有必须删除条目的 key
我有如下代码(更大库的一部分)。编译器告诉我元组没有实现特征,但我有一个元组和该元组的一个元素的实现。它适用于另一种类型的元组。 为什么元组 (BTreeSet)在这里没有匹配? use std::c
我想从 BTreeMap 中删除通过迭代找到的项目。 由于无法在迭代时删除项目,我将要删除的项目放入一个向量中。主要问题是不可能使用引用 向量,而只能使用值向量。然后必须克隆所有必须删除条目的 key
我在使用 BTreeSet::range 方法时遇到了一些问题。 use std::collections::BTreeSet; use std::ops::Bound::Included; fn m
我是不是遗漏了什么,或者没有办法让迭代器从 BTreeSet 中新插入的值开始? BTreeSet::insert只返回一个 bool 值。作为比较,C++ 中 std::map 的 insert 方
另一个基本的 Rust 问题:有人可以举一个使用 from_iter 的例子吗?创建BTreeSet ? 据推测,BTreeSet 确实实现了 FromIterator 特性,但最有用的形式是: le
我需要快速找出两个给定集合中存在的整数个数。这些集合只写入一次,但此操作将针对不同的集合对执行多次。这些集合包含 5-30 个整数,其中最大的整数是 840000。 我最初尝试迭代一个 Vec 并为每
我有一个Ref>,我想获取其内容的引用作为Vec>。 一种方法是: fn get_refs(btree: Ref>) -> Vec> { let mut result = Vec::new()
我一直在尝试实现 Bron-Kerbosch algorithm在 Rust 中为我的硕士论文。到目前为止一切正常,但是当我尝试从 BTreeSet 更改时到 HashSet出于性能比较的目的,行为变
我正在尝试从 Vec> 创建一个集合向量 ( Vec> ) .这是我目前的进展: use std::collections::BTreeSet; fn main() { // The data
我是一名优秀的程序员,十分优秀!