【问题标题】:Map on a vector without clone [duplicate]在没有克隆的向量上映射 [重复]
【发布时间】:2019-06-03 05:34:37
【问题描述】:

我正在尝试使用此签名编写一个函数,而不使用 clone() 或分配新向量:

fn mapVec(f: Fn(T) -> T, x: Vec<T>) -> Vec<T>

在我看来,这似乎是可行的。对于x 中的每个元素,我们将其传递给ff 拥有它的所有权。然后我们产生一个返回值,然后f 取得了这个传递值的所有权,如有必要,它会销毁它。然后我们将返回值放回向量中。由于我们已经获得了x 的所有权,我们可以对其进行修改,然后我们可以将其返回给调用者。

我的尝试如下:

for e in x.iter_mut() {
    *e = f(e);
}
return x;

但不幸的是,f 需要 T,而不是 &amp;mut T

我不想将mapVec 的签名更改为例如使用可变函数,如果可能的话,我希望它从外部看起来像一个纯函数,只是利用内部的变异,因为我们可以侥幸成功,因为调用者已将对象的所有权传递给我们。

【问题讨论】:

  • 如何使用 into_iter 然后将结果收集到另一个 vec 中?
  • 我已经编辑了问题,但不,我想避免新的分配,因为返回类型是相同的,我已经取得了所有权我想避免新的分配
  • 请注意,return x 作为最后的声明不被视为良好的 rust 样式。见stackoverflow.com/q/27961879
  • 为什么你认为它会做一个新的分配?编译器可以聪明地避免它。无论如何,我认为它不会花费一定的成本。

标签: rust


【解决方案1】:

您基本上遇到了replace_withtake_mut 板条箱试图解决的问题。只需将其中一个板条箱的使用放入 for 循环即可解决您的问题。

请注意注意事项。如果地图回调发生恐慌,就会发生不好的事情。这是因为您要做的是将对象移出其位置,调用函数,然后将结果放回该位置。但是如果函数没有产生结果,即恐慌,你在空白位置放什么?

【讨论】:

  • 可以通过在临时取出值的同时交换占位符来避免这些并发症
  • 为此,您需要提供一个占位符(甚至不需要是 Clone,您可以重复使用相同的占位符),或者是 Default 的类型。
  • 我建议将您的答案添加到副本中;因为它似乎不在那里。
【解决方案2】:

这个工作示例的唯一区别是回调引用T 而不是T 本身,但仍然不是可变的:

fn map_vec<F, T>(f: F, x: Vec<T>) -> Vec<T>
where
    F: Fn(&T) -> T,
{
    let mut x = x;
    for e in x.iter_mut() {
        *e = f(e);
    }
    x
}

fn main() {
    let x = vec![1, 2, 3];
    let y = map_vec(|e| e + 1, x);
    println!("{:?}", y);
}

【讨论】:

    猜你喜欢
    • 2018-08-31
    • 2018-08-06
    • 2016-02-25
    • 2012-09-23
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多