Когда вы используете оператор индексатора для Vec
или слайса, компилятор должен проверить, находится ли индекс в пределах или за пределами.
Однако, когда вы используете итераторы, эти проверки границопущены, потому что итераторы были тщательно написаны, чтобы гарантировать, что они никогда не читают за пределами.Кроме того, из-за того, как заимствование работает в Rust, структура данных не может быть видоизменена, пока существует итератор над этой структурой данных (кроме как через сам этот итератор), поэтому невозможно изменить действительные границы во время итерации.
Поскольку вы выполняете итерацию по двум различным структурам данных одновременно, вам нужно использовать адаптер итератора zip
.zip
останавливается, как только один итератор исчерпан, поэтому все еще важно проверить, что оба вектора имеют одинаковую длину.zip
создает итератор кортежей, где каждый кортеж содержит элементы в одной и той же позиции в двух исходных итераторах.Затем вы можете использовать map
для преобразования каждого кортежа в произведение двух значений.Наконец, вы захотите collect
новый итератор, сгенерированный map
в Vec
, который затем вы сможете вернуть из своей функции.collect
использует size_hint
для предварительного выделения памяти для вектора, используя Vec::with_capacity
.
/// element-wise multiplication for vecs
pub fn vec_mul<T>(v1: &[T], v2: &[T]) -> Vec<T>
where
T: std::ops::Mul<Output = T> + Copy,
{
if v1.len() != v2.len() {
panic!("Cannot multiply vectors of different lengths!")
}
v1.iter().zip(v2).map(|(&i1, &i2)| i1 * i2).collect()
}
Примечание: я изменил подпись, чтобы брать фрагменты вместо ссылокк векторам.См. Почему не рекомендуется принимать ссылку на String (& String), Vec (& Vec) или Box (& Box) в качестве аргумента функции? для получения дополнительной информации.