Rust关于Vec的Reduce方法参考

alf*_*_JS 4 functional-programming reference rust rust-cargo borrow-checker

我正在尝试将 Vec 的引用减少到其总和,以便我可以计算其平均值。不过,我遇到了编译器问题,并且我没有遵循如何不正确借用/引用事物的情况。

// Given a list of integers, use a vector and return the mean (the average value), median (when sorted, the value in the middle position), and mode (the value that occurs most often; a hash map will be helpful here) of the list.
fn main() {
    let list_of_integers = vec![200, -6_000, 3, 0, 23, 99, -1];

    let mean_ans = mean(&list_of_integers);
    // Other code that will also use list_of_integers hence why I want to reference list_of_integers so it doesn't get removed from memory

    println!("mean is {}", mean_ans);
}

fn mean(integers: &Vec<i32>) -> i32 {
    let length = integers.len() as i32;
    let sum = integers.iter().reduce(|&a, &b| &(a + b));

    match sum {
        Some(v) => v / length,
        None => 0,
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行 Cargo Run 时,我收到一个编译器错误,并且 rust-analyzer 也将reduce 方法的 &(a + b) 突出显示为错误。错误的文本如下,但我还附上了图像,以清楚地显示它所引用的内容。

// Given a list of integers, use a vector and return the mean (the average value), median (when sorted, the value in the middle position), and mode (the value that occurs most often; a hash map will be helpful here) of the list.
fn main() {
    let list_of_integers = vec![200, -6_000, 3, 0, 23, 99, -1];

    let mean_ans = mean(&list_of_integers);
    // Other code that will also use list_of_integers hence why I want to reference list_of_integers so it doesn't get removed from memory

    println!("mean is {}", mean_ans);
}

fn mean(integers: &Vec<i32>) -> i32 {
    let length = integers.len() as i32;
    let sum = integers.iter().reduce(|&a, &b| &(a + b));

    match sum {
        Some(v) => v / length,
        None => 0,
    }
}
Run Code Online (Sandbox Code Playgroud)

错误说此处创建了临时值,但返回当前函数对数据所有者的引用

我不确定这里出了什么问题,因为我理解 .iter() 返回对 Vec 的 Iter 引用,所以 a 和 b 的减少值不应该已经是 &i32 了吗?当我从 &(a + b) 中删除 & 时,出现以下编译器错误“预期&i32,找到i32帮助:考虑在此处借用:&(a + b)”。

请注意,我刚刚学习 Rust,教程还不到一半,所以请随意解释解决方案,就好像我是新手一样(因为我是新手)。

我在 VSCode 中的 Windows 10 上使用 rust 版本 1.52.1 和 rustup 版本 1.24.1。

use*_*342 13

返回&(a + b)不起作用,因为它尝试返回对临时值的引用。的结果的a + b行为就像一个未命名的局部变量,即它是闭包的局部变量,并在返回之前被销毁。解决该问题的最优雅的方法是使用integers.iter().copied()实​​际数字而不是引用来获取迭代器。这允许&在两个地方都省略。

请注意,类似的表达式&(a + b)并不总是毫无意义。当您向下传递引用时,例如传递给需要引用的函数或运算符时,它非常有用。在这种情况下,egf(&(a + b))是 , 的简写{ let _tmp = a + b; f(&tmp) },并且非常有意义。

与上述无关,您可能希望您的函数接受切片,&[i32]而不是对向量的引用。这将在向量不变的情况下工作,并使您的函数接受其他连续的内存片段,例如来自数组的内存片段。(详情请参见此处。)


Iva*_*n C 5

这里的问题是,传递给reduce的函数必须返回与原始迭代器项相同类型的值,对于通过Itertrait创建的迭代器来说,该值始终是&T。但是,您无法从函数返回引用,因为它会指向已释放的堆栈帧。
您的选择是:

  • 改为使用into_iter(),它消耗它所调用的集合并产生拥有的值,
  • 使用iter().cloned()which将克隆值,再次在拥有的值上生成一个迭代器,尽管对于非原始类型来说它可能代价高昂。

但在这种求和迭代器的特定情况下,您应该只使用iter().sum().