如何使用基于原始元素的另一个元素替换向量中的元素 [英] How can I replace an element in a vector with another element based on the original

查看:29
本文介绍了如何使用基于原始元素的另一个元素替换向量中的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑下面的程序(这是一个最小化的例子,所以不要因为我在这里尝试做的事情可以通过 HashMap<u32, Vec<MyVariant>>;):

Please consider the following program (it's a minimized example, so don't get hung up on the fact what I'm trying to do here could be better achieved with a HashMap<u32, Vec<MyVariant>>):

#[derive(PartialEq)]
enum MyVariant {
    None,
    SomeValue,
    SomeOtherValue,
    Aggregate(Vec<MyVariant>)
}

impl MyVariant {
    pub fn with(self, other: Self) -> Self {
        if self == Self::None {
            other
        } else if other == Self::None {
            self
        } else {
            Self::Aggregate(vec![self, other])
        }
    }
}

fn add_variant(vec: &mut Vec<(u32, MyVariant)>, id: u32, variant: MyVariant) {
    if let Some(item) = vec.iter_mut().find(|item| item.0 == id) {
        *item = (id, item.1.with(variant));
    } else {
        vec.push((id, variant));
    }
}

fn main() {
    let mut vec: Vec<(u32, MyVariant)> = Vec::new();
    add_variant(&mut vec, 1, MyVariant::SomeValue);
    add_variant(&mut vec, 2, MyVariant::None);
    add_variant(&mut vec, 1, MyVariant::SomeOtherValue);
}

这会在 *item = (id, item.1.with(variant)) 处失败,因为 item 是一个共享的可变引用,所以 item.1 不能移动到 with() 方法中.我尝试使用向量中的索引获取引用,但这并不能解决根本问题.

This will fail at *item = (id, item.1.with(variant)), because item is a shared mutable reference, so item.1 cannot be moved into the with() method. I tried to get a reference using an index into the vector, but that doesn't solve the underlying problem.

基本上,我想要的是一种将值暂时移出可变向量并用新的派生值替换它的方法.也许是这样的:

Basically, what I want is a method that will temporarily move a value out of a mutable vector, and replaces it with a new, derived value. Maybe something like:

impl<T> Vec<T> {
    /// Replaces the item at `index` with a new item produced by `replacer`.
    /// `replacer` receives the old item as argument.
    fn replace_with(&mut self, index: usize, replacer: Fn(T) -> T);
}

但我找不到像上面那样的方法,或者任何可以实现相同意图的技术.

But I cannot find a method like the above, or any technique that does achieve the same intent.

我怀疑我可能从错误的角度看它,所以有什么想法吗?谢谢!

I suspect I might be looking at it from the wrong angle, so any ideas? Thanks!

推荐答案

鉴于您无法复制或克隆 variant,并且 with 获得所有权,您将需要放置一个虚拟值,以避免出现未初始化的内存.你可以用 std::mem::replace:

Given that you cannot copy or clone variant, and that with takes ownership, you will need to put a dummy value were it was, to avoid the presence of unitialized memory. You can do that with std::mem::replace:

fn add_variant(vec: &mut Vec<(u32, MyVariant)>, id: u32, variant: MyVariant) {
    if let Some(item) = vec.iter_mut().find(|item| item.0 == id) {
        let old_item = std::mem::replace(&mut item.1, MyVariant::None);
        item.1 = old_item.with(variant);
    } else {
        vec.push((id, variant));
    }
}

这篇关于如何使用基于原始元素的另一个元素替换向量中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆