Rust 如何避免迭代器::平面映射中的分配?
我有一个整数的向量,我想创建一个新的向量,它包含这些整数和这些整数的平方。我可以强制这样做: 让v=vec![1, 2, 3]; 让mut new_v=Vec::new;//为了简单起见,新的而不是带有_容量。 用于v.iter中的&x{ 新(v.pushx),; 新_v.pushx*x; } 普林顿!{:?},新的_v; 但是我想使用迭代器。我想出了这个密码: 让v=vec![1, 2, 3]; 让new_v:Vec=v.iter .flat|u map|和x|vec![x,x*x] 收集 普林顿!{:?},新的_v; 但它在flat_map函数中分配了一个中间Vec 如何在没有分配的情况下使用平面地图?您可以使用一个Rust 如何避免迭代器::平面映射中的分配?,rust,iterator,declarative,Rust,Iterator,Declarative,我有一个整数的向量,我想创建一个新的向量,它包含这些整数和这些整数的平方。我可以强制这样做: 让v=vec![1, 2, 3]; 让mut new_v=Vec::new;//为了简单起见,新的而不是带有_容量。 用于v.iter中的&x{ 新(v.pushx),; 新_v.pushx*x; } 普林顿!{:?},新的_v; 但是我想使用迭代器。我想出了这个密码: 让v=vec![1, 2, 3]; 让new_v:Vec=v.iter .flat|u map|和x|vec![x,x*x] 收集 普
let v = vec![1, 2, 3];
let new_v: Vec<_> = v.iter()
.flat_map(|&x| ArrayVec::from([x, x * x]))
.collect();
通过值迭代器生成数组,这样您就不需要ArrayVec了,请参阅和链接的PRs。您可以使用
let v = vec![1, 2, 3];
let new_v: Vec<_> = v.iter()
.flat_map(|&x| ArrayVec::from([x, x * x]))
.collect();
将数组设置为按值迭代器,这样您就不需要ArrayVec了,请参阅和链接的PRs。如果您的迭代器很小,并且不需要任何外部依赖项,则可以使用和构造一个短迭代器。比如说,
use std::iter;
let v = vec![1, 2, 3];
let new_v: Vec<_> = v
.iter()
.flat_map(|&x| iter::once(x).chain(iter::once(x * x)))
.collect();
println!("{:?}", new_v);
这可以做成一个宏,不过要注意,对太多的元素使用它可能会导致达到递归限制。如果要为几十个以上的元素创建迭代器,那么进行分配可能还不错。如果您确实需要略微提高性能,nnnmmm的解决方案可能会更好
macro_rules! small_iter {
() => { std::iter::empty() };
($x: expr) => {
std::iter::once($x)
};
($x: expr, $($y: tt)*) => {
std::iter::once($x).chain(small_iter!($($y)*))
};
}
fn main() {
let v = vec![1, 2, 3];
let new_v: Vec<_> = v
.iter()
.flat_map(|&x| small_iter!(x, x * x))
.collect();
println!("{:?}", new_v);
}
如果您的迭代器很小,并且不需要任何外部依赖项,那么可以从和构造一个短迭代器。比如说,
use std::iter;
let v = vec![1, 2, 3];
let new_v: Vec<_> = v
.iter()
.flat_map(|&x| iter::once(x).chain(iter::once(x * x)))
.collect();
println!("{:?}", new_v);
这可以做成一个宏,不过要注意,对太多的元素使用它可能会导致达到递归限制。如果要为几十个以上的元素创建迭代器,那么进行分配可能还不错。如果您确实需要略微提高性能,nnnmmm的解决方案可能会更好
macro_rules! small_iter {
() => { std::iter::empty() };
($x: expr) => {
std::iter::once($x)
};
($x: expr, $($y: tt)*) => {
std::iter::once($x).chain(small_iter!($($y)*))
};
}
fn main() {
let v = vec![1, 2, 3];
let new_v: Vec<_> = v
.iter()
.flat_map(|&x| small_iter!(x, x * x))
.collect();
println!("{:?}", new_v);
}
从1.51.0版开始,struct core::array::IntoIter已经稳定。您可以这样使用它:
use core::array;
let v = vec![1, 2, 3];
let new_v: Vec<_> = v.iter()
.flat_map(|&x| array::IntoIter::new([x, x * x]))
.collect();
文档警告说,将来在为数组实现InIterator时,这可能会被弃用,但目前这是最简单的方法。从1.51.0版开始,struct core::array::InIter已经稳定。您可以这样使用它:
use core::array;
let v = vec![1, 2, 3];
let new_v: Vec<_> = v.iter()
.flat_map(|&x| array::IntoIter::new([x, x * x]))
.collect();
文档警告说,将来在为数组实现IntoIterator时,可能会不推荐使用此方法,但目前这是最简单的方法。要清楚,可能不推荐使用的方法是使用新函数创建,而不是array::IntoIter本身。如果数组真的进入迭代器,您就可以只编写平面映射|&x |[x,x*x]。更清楚的是,可能不推荐使用的是使用新函数创建,而不是array::IntoIter本身。如果数组真的进入迭代器,您就可以只编写平面映射|&x |[x,x*x]。