Rust中有一种自然的方法来迭代几个范围或迭代器的“产品”吗?
当您在多维数组或某些状态空间上进行迭代时,会出现这种情况。例如,我想考虑具有5个元素的布尔元组的所有可能值。嵌套5个for
循环有点笨拙。
答案 0 :(得分:9)
这是一个完成工作的宏:
#![feature(macro_rules)]
macro_rules! product(
($first:ident, $($next:ident),*) => (
$first.iter() $(
.flat_map(|e| std::iter::Repeat::new(e)
.zip($next.iter()))
)*
);
)
fn main() {
let a = ['A', 'B', 'C'];
let b = [1i, 4];
let c = [true, false];
let d = ['x', 'y'];
for (((a, b), c), d) in product![a, b, c, d] {
println!("{} {} {} {}", a, b, c, d);
}
}
输出:
A 1 true x
A 1 true y
A 1 false x
A 1 false y
A 4 true x
A 4 true y
etc...
宏扩展为以下
a.iter()
.flat_map(|e| std::iter::Repeat::new(e).zip(b.iter()))
.flat_map(|e| std::iter::Repeat::new(e).zip(c.iter()))
.flat_map(|e| std::iter::Repeat::new(e).zip(d.iter()))
flat_map(|e| ... )
将一系列迭代器组合到一个迭代器中。 e
是迭代器产生的元素。
std::iter::Repeat::new(e)
创建一个重复e
。
.zip( ... )
同时迭代两个迭代器,产生两个元素作为一对。
宏的解释时间稍长,因此最好阅读macro guide
我不知道这是否是最好的方法。
答案 1 :(得分:6)
itertools crate有一个非常符合人体工程学的宏(iproduct!
),用于迭代迭代器的乘积。这是一个例子:
#[macro_use]
extern crate itertools;
pub fn main() {
let a = ['A', 'B', 'C'];
let b = [1, 4];
let c = [true, false];
let d = ['x', 'y'];
for (a, b, c, d) in iproduct!(&a, &b, &c, &d) {
println!("{} {} {} {}", a, b, c, d);
}
}