在 Rust 中实现 PHP array_column

Implementing PHP array_column in Rust

我正在学习Rust,但找不到这个问题的答案。

在 PHP 中,有 array_column 方法,它是这样工作的:

给定一个数组数组(在 Rust 中这将是一个向量的向量):

$records = [
    [1,2,3],
    [1,2,3],
    [1,2,3],
    [1,2,3]
];

如果我想得到一个包含内部数组的所有第一个元素("column")的数组,我可以这样做:

$column = array_column($records, 0);

这样,例如,我得到 [1,1,1,1]。如果我将 0 更改为 1,我会得到 [2,2,2,2] 等等。

由于 Rust 中没有 array_column 等效项(即:我找不到它),用向量的向量实现类似行为的最佳方法是什么?

我决定使用迭代器,就像您在评论中尝试的那样。

此版本适用于任何可克隆值(包括数字)。我们遍历子向量,并为每个子向量调用一个 get 方法,如果我们要求越界,它会产生向量的一个元素 Some(&e)None

and_then 然后从 get 接受一个值,如果它是 None,那么返回 None,否则,如果它是 Some(&e) 那么Some(e.clone()) 被返回,即我们克隆值(因为我们只有对 get 中值的引用,我们无法存储它,我们必须复制该值)。

collect 然后与 Iter<Option<T>> 一起工作,它可以方便地将它转换为 Option<Vec<T>>,即它 returns None 如果一些 None s 在迭代器中(这意味着某些数组的大小不够大),或者 returns Some(Vec<T>),如果一切正常的话。

fn main() {
    let array = vec![
        vec![1, 2, 3, 4],
        vec![1, 2, 3, 4, 5],
        vec![1, 2, 3, 4],
        vec![1, 2, 3, 4],
    ];
    let ac = array_column(&array, 0);
    println!("{:?}", ac); // Some([1, 1, 1, 1])

    let ac = array_column(&array, 3);
    println!("{:?}", ac); // Some([4, 4, 4, 4])

    let ac = array_column(&array, 4); // None
    println!("{:?}", ac);
}

fn array_column<T: Clone>(array: &Vec<Vec<T>>, column: usize) -> Option<Vec<T>> {
    array.iter()
        .map( |subvec| subvec.get(column).and_then(|e| Some(e.clone())) )
        .collect()
}

很好,但您也可以使用引用来概括它,因此项目不需要 Clone:

fn array_column<'a, T>(array: &'a Vec<Vec<T>>, column: usize) -> Option<Vec<&'a T>> {
    array.iter()
        .map( |subvec| subvec.get(column) )
        .collect()
}

Playground