Pregunta

Editor's note: This question's example is from a version of Rust prior to 1.0 and references types and methods no longer found in Rust. The answers still contain valuable information.

The following code

let mut numbers = new_serial.as_bytes().iter().map(|&x| (x - 48));
let sum = numbers.sum(); 

results in the following error:

std::iter::Map<,&u8,u8,std::slice::Items<,u8>>` does not implement any method in scope named `sum`

What must I do to sum an array of bytes?

The following works:

for byte in new_serial.as_bytes().iter() {
    sum = sum + (byte - 48);
}
¿Fue útil?

Solución

Iterator::sum was stabilized in Rust 1.11.0. You can get an iterator from your array/slice/Vec and then use sum:

fn main() {
    let a = [1, 2, 3, 4, 5];
    let sum: u8 = a.iter().sum();
    println!("the total sum is: {}", sum);
}

Of special note is that you need to specify the type to sum into (sum: u8) as the method allows for multiple implementations. See Why can't Rust infer the resulting type of Iterator::sum? for more information.


Applied to your original example:

let new_serial = "01234";
let sum: u8 = new_serial.as_bytes().iter().map(|&x| x - 48).sum();
println!("{}", sum);

As an aside, it's likely more clear if you use b'0' instead of 48.

Otros consejos

If performance is important, consider using an implementation that helps the compiler at producing SIMD instructions.

For example, for f32, using 16 lanes (total of 512 bits):

use std::convert::TryInto;

const LANES: usize = 16;

pub fn simd_sum(values: &[f32]) -> f32 {
    let chunks = values.chunks_exact(LANES);
    let remainder = chunks.remainder();

    let sum = chunks.fold([0.0f32; LANES], |mut acc, chunk| {
        let chunk: [f32; LANES] = chunk.try_into().unwrap();
        for i in 0..LANES {
            acc[i] += chunk[i];
        }
        acc
    });

    let remainder: f32 = remainder.iter().copied().sum();

    let mut reduced = 0.0f32;
    for i in 0..LANES {
        reduced += sum[i];
    }
    reduced + remainder
}

pub fn naive_sum(values: &[f32]) -> f32 {
    values.iter().sum()
}

for

let values = (0..513).map(|x| x as f32).collect::<Vec<_>>();

the above is 10x faster than values.iter().sum() on my computer:

simd_sum             time:   [77.341 ns 77.773 ns 78.378 ns]
naive_sum               time:   [739.97 ns 740.48 ns 740.97 ns]

and ~10% slower than using packed_simd2 (but it does not require nightly).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top