Ваша переменная prod
передает состояние от одного элемента к следующему, а это не то, что делает отображение.Сопоставления работают с каждым элементом независимо, что облегчает их распараллеливание и упрощает рассуждение.Результат, который вы запрашиваете, должен быть точным при правильном сканировании (обратный случай префиксной суммы ), но я не уверен, что есть удобные методы для сбора изправильно (вероятно, самый простой изменяемый способ - использовать VecDeque::push_front
).Это заставило меня выполнить операцию за два прохода для моей первой версии:
fn main() {
let input: Vec<usize> = vec![2, 3, 4];
let initprod = 1;
let prev: Vec<usize> = input
.iter()
.rev()
.scan(initprod, |prod, &v| {
*prod *= v;
Some(*prod)
}).collect();
let p: Vec<usize> = prev.into_iter().rev().collect();
println!("{:?}", p);
}
Обратите внимание, что initprod
является неизменным;prod
несет государство.Использование into_iter
также означает, что prev
потребляется.Мы могли бы использовать vec.reverse
, как показано mcarton, но тогда нам нужна переменная переменная.Сканы могут быть распараллелены, но в меньшей степени, чем карты.См., Например, обсуждение о добавлении их в район .Можно также рассмотреть вопрос о том, должен ли ExactSizeIterator
разрешить обратный сбор в обычный вектор, но стандартная библиотека scan
метод разбивает известный размер, используя Option
(который поnext
конвенция превращает его в "сканирование на время").
Вот несколько вариантов копирования, использующих предварительно выделенный VecDeque для сбора справа.Я использовал дополнительную область, чтобы ограничить изменчивость.Также требуется Rust 1.21 или более поздняя версия, чтобы использовать for_each
.Отслеживание количества элементов и структуры кольцевого буфера требует лишних затрат, но все же, по крайней мере, несколько разборчиво.
use std::collections::VecDeque;
fn main() {
let input: Vec<usize> = vec![2,3,4];
let p = {
let mut pmut = VecDeque::with_capacity(input.len());
let initprod = 1;
input
.iter()
.rev()
.scan(initprod, |prod, &v| {
*prod *= v;
Some(*prod)
})
.for_each(|v| {
pmut.push_front(v)
});
pmut
};
println!("{:?}", p);
}
Кстати, после старой поговорки о том, что программисты на Лиспе знают ценность всего и ничего не стоят, вот версия на Haskell, я не знаю, насколько она неэффективна:
scanr1 (*) [2, 3, 4]