沿维度求和数组

时间:2016-10-25 14:47:40

标签: arrays sum rust

在许多语言中(Fortran,Matlab / Octave,Julia等),像sum(array,n)这样的表达式将沿n:th维度对数组的值求和,并输出一个较低维度的数组。在Rust中有相同的东西吗?

我试过了:

fn main() {
    let arr1: [f64; 5] = [1.1, 1.2, 2.3, 3.4, 4.5555];
    println!("this {}", arr1.iter().sum())
}

出现此错误:

error[E0282]: unable to infer enough type information about `_`
 --> src/main.rs:3:37
  |
3 |     println!("this {}", arr1.iter().sum())
  |                                     ^^^ cannot infer type for `_`
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:3:5: 3:43 note: in this expansion of println! (defined in <std macros>)
  |
  = note: type annotations or generic parameter binding required

2 个答案:

答案 0 :(得分:3)

在这种情况下,您必须明确指定元素的类型:

println!("this {}", arr1.iter().sum::<f64>())

你非常亲密:)

@ E_net4建议的另一个选项是使用单独的绑定:

let res: f64 = arr1.iter().sum();
println!("this {}", res)

答案 1 :(得分:1)

在其他一些问题中解释了“无法推断出有关_”的错误消息的类型信息。请参阅Error: unable to infer enough type information about `_`; type annotations or generic parameter binding requiredUnable to infer enough type information about _; type annotations or generic parameter binding required。基本上,这意味着编译器没有足够的信息来指定函数或数据类型中的所有类型参数。

然而,这种特殊情况可能会引起一些混淆:为什么Iterator.sum()只能将得到的和的类型推断为迭代器的Item?假设加起来f64,我们期待f64作为结果,对吧?嗯,方法sum实际上是这样定义的:

fn sum<S>(self) -> S 
    where S: Sum<Self::Item>

S实现了另一种带有迭代器的sum函数(参见trait Sum):

pub trait Sum<A = Self> {
    fn sum<I>(iter: I) -> Self where I: Iterator<Item=A>;
}

这个特性使我们可以自由地对数字和数字的引用进行求和:

static MAGIC_CODE: u32 = 0xDEADBEEF;
static BLAND_CODE: u32 = 0x1234ABCD;

fn main() {

    let sum1: u32 = vec![MAGIC_CODE, BLAND_CODE] // vec! infers to Vec<u32>
        .into_iter().sum();

    let sum2 = vec![&MAGIC_CODE, &BLAND_CODE] // vec! infers to Vec<&u32>
        .into_iter().sum::<u32>();


    assert_eq!(sum1, sum2);
}

另一方面,这也意味着总和的定义变得更加宽松:实现Sum<u32>(或Sum<&u32>)的任何其他数据类型都可以在上面的代码中占据一席之地,这导致对上述含糊不清的看法。出于演示的目的,此代码还编译:

use std::iter::Sum;

struct Accumulator(bool);

impl Sum<u32> for Accumulator {
    fn sum<I: Iterator<Item = u32>>(mut iter: I) -> Self {
        Accumulator(iter.any(|v| v != 0))
    }
}

fn main() {
    let sum3: Accumulator = {
        let data = vec![MAGIC_CODE, BLAND_CODE];

        data.into_iter().sum()
    };

    assert!(sum3.0);
}

Full code on Playground