有没有一种方法将两个迭代器合并到同一个 Vec 中?

11

我有两个迭代器,最终会合并到同一个Vec中,但在合并之前需要对结果进行过滤。例如:

let a = vec![1, 2, 3, 4].into_iter().map(|x| x * 2);
let b = vec![0, 3, 5, 6, 7].into_iter().map(|x| x * 3);
let c = a + b;
assert_eq!(
    c.filter(|&x| x > 5).collect::<Vec<u8>>(),
    vec![6, 8, 9, 15, 18, 21]
);

我可以这样做:

可能可以像这样做:

let mut a = vec![1, 2, 3, 4]
    .into_iter()
    .map(|x| x * 2)
    .collect::<Vec<u8>>();
let b = vec![0, 3, 5, 6, 7]
    .into_iter()
    .map(|x| x * 3)
    .collect::<Vec<u8>>();
a.extend(b);
assert_eq!(
    a.into_iter().filter(|&x| x > 5).collect::<Vec<u8>>(),
    vec![6, 8, 9, 15, 18, 21]
);

但是在我的情况下额外的分配会降低性能(是的,我已经检查过了!)

2个回答

23

您正在寻找Iterator::chain

let a = vec![1, 2, 3, 4].into_iter().map(|x| x * 2);
let b = vec![0, 3, 5, 6, 7].into_iter().map(|x| x * 3);
let c = a.chain(b);
assert_eq!(
    c.filter(|&x| x > 5).collect::<Vec<u8>>(),
    vec![6, 8, 9, 15, 18, 21]
);

2
另外,您可以使用 extend() 函数:
let a = (0..500000).map(|x| x * 2);
let b = (0..500000).map(|x| x * 3);
let mut c = Vec::with_capacity(a.size_hint().1.unwrap() + b.size_hint().1.unwrap());
c.extend(a);
c.extend(b);

这要求您明确使用with_capacity(),而chain()collect()本可以为您完成。在已经构建a的情况下,使用extend()将比构建临时向量更合适。
在本例中,我没有发现chain()extend()之间有任何基准差异(benchmark

这并未进行筛选。Sebastian Redl

正确!修正此错误后,某些情况下LLVM不再优化chain()。使用extend()版本:
let a = (0..500000).map(|x| x * 2);
let b = (0..500000).map(|x| x * 3);
let mut c = Vec::with_capacity(a.size_hint().1.unwrap() + b.size_hint().1.unwrap());
c.extend(a.filter(|&x| x > 5));
c.extend(b.filter(|&x| x > 5));

比起使用chain的版本,速度快了两倍(这正是我一开始期望的)。
let a = (0..500000).map(|x| x * 2);
let b = (0..500000).map(|x| x * 3);
let _c: Vec<_> = a.chain(b).filter(|&x| x > 5).collect();

(基准测试)


这并不执行过滤。 - Sebastian Redl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接