Rust 获取BTreeSet的第一个成员

Rust 获取BTreeSet的第一个成员,rust,set,Rust,Set,在Rust中,我有一个b树集,用来保持我的值有序。我有一个循环,它应该检索并删除集合中的第一个(最低)成员。我正在使用克隆迭代器检索第一个成员。代码如下: use std::collections::BTreeSet; fn main() { let mut start_nodes = BTreeSet::new(); // add items to the set while !start_nodes.is_empty() { let mut st

在Rust中,我有一个
b树集
,用来保持我的值有序。我有一个循环,它应该检索并删除集合中的第一个(最低)成员。我正在使用克隆迭代器检索第一个成员。代码如下:

use std::collections::BTreeSet;

fn main() {
    let mut start_nodes = BTreeSet::new();

    // add items to the set

    while !start_nodes.is_empty() {
        let mut start_iter = start_nodes.iter();
        let mut start_iter_cloned = start_iter.cloned();
        let n = start_iter_cloned.next().unwrap();

        start_nodes.remove(&n);

    }
}
但是,这给了我以下编译错误:

error[E0502]:无法将'start_nodes'借用为可变的,因为它也被借用为不可变的
-->进度rs:60:6
|
56 |让mut start_iter=start_nodes.iter();
|--------此处发生不可变借用
...
60 |启动_节点。删除(&n);
|^^^^^^^^^^^^^^^此处发生可变借用
...
77 |     }
|-不可变的借阅到此结束
为什么
start\u nodes.iter()
被认为是不可变的借用?我应该采取什么方法来获得第一个成员


我正在使用版本
1.14.0
(不是选择)。

不确定这是最佳方法,但我通过引入一个新的作用域来修复它,以确保可变借用在可变借用发生之前结束:

use std::collections::BTreeSet;

fn main() {
    let mut start_nodes = BTreeSet::new();

    // add items to the set

    while !start_nodes.is_empty() {
        let mut n = 0;

        {
            let mut start_iter = start_nodes.iter();
            let mut start_iter_cloned = start_iter.cloned();

            let x = &mut n;
            *x = start_iter_cloned.next().unwrap();
        }

        start_nodes.remove(&n);    
    } 
}
为什么
start\u nodes.iter()
被认为是不可变的借用

无论何时提出这样的问题,都需要查看函数的原型,在本例中是
BTreeSet::iter()的原型

iter()的定义中未明确提及寿命
'a
;但是,生存期省略规则使函数定义等效于

fn iter<'a>(&'a self) -> Iter<'a, T>
然而,请注意,这段代码是不必要的冗长。您创建的新迭代器及其克隆版本只存在于新范围内,并且它们实际上没有用于任何其他目的,因此您也可以编写

while !start_nodes.is_empty() {
    let n = start_nodes.iter().next().unwrap().clone();
    start_nodes.remove(&n);
}
它的作用完全相同,并通过避免将中间值存储在变量中来避免长寿借款的问题,以确保它们的生存期在表达式之后立即结束

最后,虽然您没有给出用例的全部细节,但我强烈怀疑您最好使用
BinaryHeap
而不是
BTreeSet

use std::collections::BinaryHeap;

fn main() {
    let mut start_nodes = BinaryHeap::new();
    start_nodes.push(42);
    while let Some(n) = start_nodes.pop() {
        // Do something with `n`
    }
}

此代码更短、更简单,完全避免了借用检查器的问题,而且效率更高。

您的Rust 2018示例(使用NLL)。@LukasKalbertodt谢谢,您是对的。不幸的是,使用最新的编译器对我来说不是一个解决方案,因为这是一个uni评估,标记环境使用Rust 1.14.0。然而,如果我知道我不是在做傻事,而是出于兴趣,我应该能够让它工作起来:什么大学?总是感兴趣的是在哪里教生锈。@卢卡斯卡尔伯托特肯特大学。“不过,这可能会让你失望,因为这只是一个研究各种语言的模块,所以生锈的报道相当肤浅。”Stargateur道歉,编辑。我发布的时候没有意识到编译器不是最新版本。
while !start_nodes.is_empty() {
    let n = {
        let mut start_iter = start_nodes.iter();
        let mut start_iter_cloned = start_iter.cloned();
        start_iter_cloned.next().unwrap()
    };
    start_nodes.remove(&n);
}
while !start_nodes.is_empty() {
    let n = start_nodes.iter().next().unwrap().clone();
    start_nodes.remove(&n);
}
use std::collections::BinaryHeap;

fn main() {
    let mut start_nodes = BinaryHeap::new();
    start_nodes.push(42);
    while let Some(n) = start_nodes.pop() {
        // Do something with `n`
    }
}