在 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()
}
我正在学习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()
}