Как я могу создать `Vec` из `Итератора<Item=

#rust #reference

#Ржавчина #ссылка #итератор #владение

Вопрос:

Я столкнулся с ошибкой при попытке использовать функцию get_even_numbers() для заимствования vec v , передавая ее по ссылке amp;v , а не по значению v .

 fn get_even_numbers(v: amp;Vec<i32>) -> Vec<i32> {
    v.iter().filter(|x| x % 2 == 0).collect()
}

fn main() {
    let v: Vec<i32> = (0..10).collect();
    let even: Vec<i32> = get_even_numbers(amp;v);
    println!("Even numbers: {:?}", even);
}
  
 error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `amp;i32`
 --> src/main.rs:2:37
  |
2 |     v.iter().filter(|x| x % 2 == 0).collect()
  |                                     ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=amp;i32>`
  |
  = help: the trait `FromIterator<amp;i32>` is not implemented for `Vec<i32>`
  = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
note: required by a bound in `collect`
  

Почему приведенное выше выдает ошибку, но передача ее по значению не дает, как показано ниже?

 fn get_even_numbers(v: Vec<i32>) -> Vec<i32> {
    v.into_iter().filter(|x| x % 2 == 0).collect()
}

fn main() {
    let v: Vec<i32> = (0..10).collect();
    let even: Vec<i32> = get_even_numbers(v);
    println!("Even numbers: {:?}", even);
}
  
 Even numbers: [0, 2, 4, 6, 8]
  

Я использовал .iter() внутри функции при передаче по ссылке и .into_iter() при передаче по значению, не уверен, что это правильные функции для использования.

Комментарии:

1. Перебор заимствованного вектора перебирает ссылки на значения. Для передачи фактических значений потребуется переместить их из вектора, а это разрешено только в том случае, если сам вектор используется в процессе. Именно поэтому версия с into_iter() works — поскольку into_iter() она использует вектор, она передает право собственности на элементы vector потребителю итератора. Поскольку i32 is Copy , вы можете исправить заимствованную версию, добавив разыменование, например, изменив .collect() на .copied().collect() .

Ответ №1:

Используйте v.iter().filter(|x| x % 2 == 0).cloned().collect() . Это (тривиально) клонирует каждую из amp;i32 ссылок в фактические i32 значения.

Комментарии:

1. Вы можете использовать copied() вместо cloned() того, чтобы утверждать (во время компиляции), что клон тривиален.