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);
}
The Vec type allows to access values by index, because it implements the Index trait. An example will be more explicit: let v = vec![ 0, 2, 4, 6]; println!("
In Rust, there are several ways to initialize a vector. In order to initialize a vector via the new() method call, we use the double colon operator: let mut vec = Vec::new();
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.
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 nonsimd_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:
nonsimd_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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With