我正在编写一个库,它使用Vec<Vec<T>>
类型以列主要顺序存储数据(每个内部Vec
代表一列)。用户可以创建具有任何行和列长度的Vec<Vec<T>>
,但所有列都被约束为相同的长度。
我有时需要有效地逐行遍历Vec<Vec<T>>
。我想不改变数组类型,因为大多数时候我需要“按列向量”迭代(一次一个完整的列向量)。
除非我遗漏了某些东西,否则Iterator::zip
不是一个选项,因为我事先并不知道列向量的数量。 Itertools::izip
和Itertools::multizip
也不可行。
这是我的示例代码:
let array = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
let mut iterators: Vec<_> = array.iter().map(|x| x.iter()).collect();
for _ in 0..array[0].len() {
let values: Vec<_> = iterators.iter_mut().map(|x| x.next().unwrap()).collect();
dbg!(values);
}
我应该在开始迭代之前定义一个可变的values
向量以避免在每个周期进行分配,或者编译器是否会处理这种优化?自己找到它最简单的方法是什么?
有更有效/惯用的解决方案吗?
有两种方法可以创建迭代器:使用现有的迭代器适配器或实现自定义迭代器。
让我们采用第二种方法并定义一个带有迭代器向量的自定义迭代器类型:
struct DynamicZip<I>
where I: Iterator {
iterators: Vec<I>
}
让我们提供一个迭代器实现:
impl<I, T> Iterator for DynamicZip<I>
where I: Iterator<Item = T> {
type Item = Vec<T>;
fn next(&mut self) -> Option<Self::Item> {
let output: Option<Vec<T>> = self.iterators.iter_mut().map(|iter| iter.next()).collect()
output
}
}
我们完成了!
fn main() {
let array = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
let iterators: Vec<_> = array.into_iter().map(|v| v.into_iter()).collect();
let dz = DynamicZip { iterators: iterators };
// use the Iterator type we just defined
for column in dz {
println!("{:?}", column)
}
}
将产生输出
[1, 4, 7]
[2, 5, 8]
[3, 6, 9]
你的qazxsw poi是一个面向列的矩阵,其中每个内部qazxsw poi都是一列,因此,通过简单地执行Vec<Vec<T>>
操作,可以在运行时知道列数。
通过行和列,可以更轻松地创建Vec
。这是一个例子:
array.len()