Collections 如何更新BTreeSet中的所有值?

Collections 如何更新BTreeSet中的所有值?,collections,module,rust,Collections,Module,Rust,我有一个集合,它是某个模块中结构中的一个字段。我想从另一个模块更新集合中的所有值 我写了一些代码来模仿我想要实现的东西。它缩短了一点,但我认为它有所有需要的部件。在这段代码中没有保存集合的结构,但是假设这是一个返回集合的getter。我在评论中补充了我认为它应该是什么样子 pub mod pos { use std::cmp::{Ordering, PartialEq}; #[derive(PartialOrd, PartialEq, Eq, Hash, Debug, Copy

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

我写了一些代码来模仿我想要实现的东西。它缩短了一点,但我认为它有所有需要的部件。在这段代码中没有保存集合的结构,但是假设这是一个返回集合的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);
    }
}

我在没有借钱的情况下成功了,但我希望借钱也能成功。我想实现这一目标的方法不止一种。欢迎评论帮助我的Rust connect。

BTreeSet
没有实现(这会破坏树)


只能对使用
mut
实现
IntoIterator
的类型执行此操作,如
impl
BTreeSet
未实现(这将破坏树)


只能对使用
mut
实现
IntoIterator
的类型执行此操作,如
impl不能对属于
HashSet
BTreeSet
的项进行变异,因为项的值决定了它们的存储和访问方式。如果你对它们进行变异,就像,你会打破收藏的机制。对于
散列集
,您需要更改项目的散列,该散列决定了数据存储的位置。对于
b树集
,算法基于项目的排序方式

您可以通过拥有所有权来实现这一点,因为您使用原始集合并生成一个新的、格式良好的集合。你不能拥有借来的价值,因为这会留下一个悬空的指针,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();

不能对属于
HashSet
BTreeSet
的项进行变异,因为项的值决定了它们的存储和访问方式。如果你对它们进行变异,就像,你会打破收藏的机制。对于
散列集
,您需要更改项目的散列,该散列决定了数据存储的位置。对于
b树集
,算法基于项目的排序方式

您可以通过拥有所有权来实现这一点,因为您使用原始集合并生成一个新的、格式良好的集合。你不能拥有借来的价值,因为这会留下一个悬空的指针,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();


是什么让你在这里使用
到iter
/
地图
/
收集
。我现在正在学习Rust,我正在阅读有关Java 8+流的文章,我是Java 8+流的粉丝。所以我试着去做一件“简单的事情”。是什么让你用
来绘制地图的呢。我现在正在学习Rust,我正在阅读有关Java 8+流的文章,我是Java 8+流的粉丝。所以我试着去做我认为“简单的事情”。这里有没有一种方法来编辑代码,使其与BTreeSet一起工作?我需要独特性和秩序。不知何故说要更改getter或更改更新代码的工作方式??我觉得这应该是可能的。我所做的事情可能是这样的:获取集合引用>从中创建新的
TreeSet
,将新创建的
TreeSet
分配给引用。但是在生锈的地方怎么做呢。。我没有太多的经验。甚至可能:获取集合(借用它)>获取(从集合中移除)每个元素>更新它>插入回集合更新的元素。在这种情况下,树不会被破坏。@my-请参阅其他答案,但如果您需要频繁变异所有元素,可能您没有使用好的集合。但是如果没有更多的上下文,我不能给你更多的建议。我怀疑更新会很频繁。在最坏的情况下——是的,但我认为这只是边缘情况。我正在某个网站上进行编码挑战。这里有没有一种方法可以编辑代码,使其与BTreeSet一起工作?我需要独特性和秩序。不知何故说要更改getter或更改更新代码的工作方式??我觉得这应该是可能的。我所做的事情可能是这样的:获取集合引用>从中创建新的
TreeSet
,将新创建的
TreeSet
分配给引用。但是在生锈的地方怎么做呢。。我没有太多的经验。甚至可能:获取集合(借用它)>获取(从集合中移除)每个元素>更新它>插入回集合更新的元素。在这种情况下,树不会被破坏。@my-请参阅其他答案,但如果您需要频繁变异所有元素,可能您没有使用好的集合。但是如果没有更多的上下文,我不能给你更多的建议。我怀疑更新会很频繁。在最坏的情况下——是的,但我认为这只是边缘情况。我正在某个网站上进行编码挑战。这里是否有可能进行smth,如:获取集合(借用它)>获取(从集合中移除)每个元素>更新它>插入到集合更新元素。那样的话,这棵树就不会坏了。我假设在插入时将重新计算哈希。我说得对吗?没错。但是,它可能比仅仅重建整个集合效率低,因为
insert
remove
都是O(logn)复杂度。是的,你说得对。如果集合有方法
update\u all()
,这将需要闭包来分别更新每个元素,那就太好了。那很方便。您能否更新您的答案以包含替换元件的代码?因为我一直在想办法。无论如何,我接受你的回答