Каков идиоматический способ преобразования Vec ссылок в Vec значений? - PullRequest
0 голосов
/ 02 ноября 2018

Моя функция возвращает Vec ссылок на кортеж, но мне нужно Vec кортежей:

use std::collections::HashSet;

fn main() {
    let maxs: HashSet<(usize, usize)> = HashSet::new();
    let mins: HashSet<(usize, usize)> = HashSet::new();
    let intersection = maxs.intersection(&mins).collect::<Vec<&(usize, usize)>>();
}

Как мне сделать преобразование?

Ошибка:

19 |     maxs.intersection(&mins).collect::<Vec<&(usize, usize)>>()
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
   |
   = note: expected type `std::vec::Vec<(usize, usize)>`
          found type `std::vec::Vec<&(usize, usize)>`

Я использую цикл for для преобразования , но мне это не нравится, и я думаю, что должен быть режим идиоматическим образом:

for t in maxs.intersection(&mins).collect::<Vec<&(usize, usize)>>().iter() {
    output.push(**t);
}

1 Ответ

0 голосов
/ 02 ноября 2018

Обновление с 1.36.0

Rust 1.36.0 введен copied, который работает как cloned, но использует черту Copy, которая требует, чтобы копия была дешевой (например, только memcpy) , Если у вас есть примитивные типы или типы, которые реализуют Copy, вы можете использовать это вместо этого.


Чтобы ваш пример работал, используйте cloned, а затем collect.

let maxs: HashSet<(usize,usize)> = HashSet::new();
let mins: HashSet<(usize,usize)> = HashSet::new();
let output: Vec<(usize, usize)> = maxs.intersection(&mins).cloned().collect();

Это решение будет работать с любым типом, кроме орудий Clone:

pub fn clone_vec<T: Clone>(vec: Vec<&T>) -> Vec<T> {
    vec.into_iter().cloned().collect()
}

Если ваша функция принимает срез, вы должны использовать cloned дважды.

pub fn clone_slice<T: Clone>(slice: &[&T]) -> Vec<T> {
    slice.iter().cloned().cloned().collect()
}

Причина этого в том, что iter() возвращает итератор по ссылкам на фрагмент, что приводит к &&T.


Если у вас есть тип, который не реализует Clone, вы можете имитировать поведение с помощью map

pub struct Foo(u32);

impl Foo {
    fn dup(&self) -> Self {
        Foo(self.0)
    }
}

pub fn clone_vec(vec: Vec<&Foo>) -> Vec<Foo> {
    vec.into_iter().map(|f| f.dup()).collect()
}

pub fn clone_vec2(vec: Vec<&Foo>) -> Vec<Foo> {
    // this function is identical to `ret_tup`, but with another syntax
    vec.into_iter().map(Foo::dup).collect()
}

( площадка * * тысяча пятьдесят два) * * тысяча пятьдесят три

...