如何在Flat_map中获取值的所有权

Rya*_*729 3 iterator rust

以下是我的问题的简化/摘要版本:

fn main() {
    let foo_selectors = vec![0, 1];

    let foos: Vec<_> = foo_selectors
        .into_iter()
        .flat_map(|i| get_foo(i).into_iter())
        .collect();

    println!("{:?}", foos);
}

fn get_foo(i: u8) -> [u8; 3] {
    if i % 2 == 0 {
        [1, 2, 3]
    } else {
        [4, 5, 6]
    }
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接

我收到以下错误消息:

fn main() {
    let foo_selectors = vec![0, 1];

    let foos: Vec<_> = foo_selectors
        .into_iter()
        .flat_map(|i| get_foo(i).into_iter())
        .collect();

    println!("{:?}", foos);
}

fn get_foo(i: u8) -> [u8; 3] {
    if i % 2 == 0 {
        [1, 2, 3]
    } else {
        [4, 5, 6]
    }
}
Run Code Online (Sandbox Code Playgroud)

该错误消息抱怨借用,但是into_iter据我所知,我已经在很多地方使用了迭代值的所有权。我想拥有从返回的值的所有权get_foo并将其元素插入foos。我怎样才能做到这一点?

She*_*ter 5

如何在Flat_map中获取值的所有权

这里没有什么特别的flat_map。调用时get_foo,返回值的所有权会转移到调用方,就像Rust中的其他任何地方一样。

据我所知,我到处都使用过in_iter,它拥有迭代值的所有权。

通常,是的,但不是数组。有关原因,请参见下面的链接问题。这是问题的根源。该flat_map闭包拥有的结果get_foo,然后您对其进行引用。该引用不能超出闭包,但这就是您要执行的操作。

解决方法是,您可以Vec从函数中返回a :

fn get_foo(i: u8) -> Vec<u8> {
    if i % 2 == 0 {
        vec![1, 2, 3]
    } else {
        vec![4, 5, 6]
    }
}
Run Code Online (Sandbox Code Playgroud)

您也可以将返回的数组转换为调用Vec内部flat_map

如果您认为情况允许,可以实现自己的迭代器:

struct CloneArrayIter<T> {
    arr: [T; 3],
    idx: usize,
}

impl<T> CloneArrayIter<T> {
    fn new(arr: [T; 3]) -> Self {
        Self { arr, idx: 0 }
    }
}

impl<T> Iterator for CloneArrayIter<T>
where
    T: Clone,
{
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.idx < 3 {
            let value = self.arr[self.idx].clone();
            self.idx += 1;
            Some(value)
        } else {
            None
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并用作 .flat_map(|i| CloneArrayIter::new(get_foo(i)))

我可能只使用ArrayVecfrom arrayvec

extern crate arrayvec;

use arrayvec::ArrayVec;

fn main() {
    let foo_selectors = vec![0, 1];

    let foos: Vec<_> = foo_selectors
        .into_iter()
        .flat_map(|i| get_foo(i))
        .collect();

    println!("{:?}", foos);
}

fn get_foo(i: u8) -> ArrayVec<[u8; 3]> {
    if i % 2 == 0 { [1, 2, 3] } else { [4, 5, 6] }.into()
}
Run Code Online (Sandbox Code Playgroud)

也可以看看: