gpt4 book ai didi

collections - 如何更新 BTreeSet 中的所有值?

转载 作者:行者123 更新时间:2023-11-29 08:23:22 24 4
gpt4 key购买 nike

我有一个集合,它是某个模块中结构中的一个字段。我想从另一个模块更新集合中的所有值。

我写了一些代码来模仿我想要实现的目标。它缩短了一点,但我认为它具有所有需要的部分。这段代码中没有保存集合的结构,但可以想象这是一个返回集合的 getter。我在评论中添加了我认为它应该是什么样子。

pub mod pos {
use std::cmp::{Ordering, PartialEq};

#[derive(PartialOrd, PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub struct Pos {
pub x: i32,
pub y: i32,
}

#[allow(dead_code)]
impl Pos {
pub fn of(x: i32, y: i32) -> Self {
Self { x, y }
}

pub fn offset(&mut self, pos: &Self) -> Self {
self.x += pos.x;
self.y += pos.y;

*self
}
}

impl Ord for Pos {
fn cmp(&self, other: &Self) -> Ordering {
if self.x < other.x {
Ordering::Less
} else if self.eq(other) {
Ordering::Equal
} else {
Ordering::Greater
}
}
}
}

mod test {
use crate::pos::Pos;
use std::collections::BTreeSet;

#[test]
fn test_iterators() {
let mut data_in_some_strct: BTreeSet<Pos> = BTreeSet::new();

data_in_some_strct.insert(Pos::of(1, 1));
data_in_some_strct.insert(Pos::of(2, 2));
data_in_some_strct.insert(Pos::of(3, 3));
data_in_some_strct.insert(Pos::of(4, 4));

// mimic getter call ( get_data(&mut self) -> &BTreeSet<Pos> {...}
// let set = data_in_some_strct; // works, but not a reference
let set = &data_in_some_strct; // doesn't work, How to adjust code to make it work??

data_in_some_strct = set
.into_iter()
.map(|mut p| p.offset(&Pos::of(1, 0)))
.inspect(|p| println!("{:?}", *p))
.collect();

assert_eq!(data_in_some_strct.contains(&Pos::of(2, 1)), true);
assert_eq!(data_in_some_strct.contains(&Pos::of(3, 2)), true);
assert_eq!(data_in_some_strct.contains(&Pos::of(4, 3)), true);
assert_eq!(data_in_some_strct.contains(&Pos::of(5, 4)), true);
}
}

Playground

error[E0596]: cannot borrow `*p` as mutable, as it is behind a `&` reference
--> src/lib.rs:56:26
|
56 | .map(|mut p| p.offset(&Pos::of(1, 0)))
| - ^ `p` is a `&` reference, so the data it refers to cannot be borrowed as mutable
| |
| help: consider changing this to be a mutable reference: `&mut pos::Pos`

我设法让它在不借用的情况下工作,但我想让它在借用的情况下工作。我想有不止一种方法可以实现它。评论帮助我的 Rust brain dendrites欢迎联系。

最佳答案

您不能改变属于 HashSetBTreeSet 的项目,因为项目的 决定了它们的存储方式和访问过。如果你改变它们,那么 Stargateur mentioned ,你会破坏集合的机制。在 HashSet 的情况下,您可以更改项目的哈希值,它决定了数据的存储位置。对于 BTreeSet,算法基于项目的排序方式。

您可以通过取得所有权来做到这一点,因为您使用了原始集合并生成了一个新的、格式良好的集合。您不能取得借用值的所有权,因为那样会留下悬空指针,而 Rust 不允许您这么做。

一种可能的解决方案是暂时用一个空的集合替换原来的集合。然后,您可以像在您的工作代码中那样获得其内容的所有权,并最终在原始代码上编写新更新的集合:

let set = std::mem::replace(&mut data_in_some_strct, BTreeSet::new());

data_in_some_strct = set.into_iter()
.map(|mut p| p.offset(&Pos::of(1,0)))
.inspect(|p| println!("{:?}", *p))
.collect();

关于collections - 如何更新 BTreeSet 中的所有值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54697274/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com