rust 如何使用Iterator得到2个向量的笛卡尔积?

jk9hmnmh  于 2022-12-19  发布在  其他
关注(0)|答案(3)|浏览(304)

我有两个Vec

let x = vec!['1', '2', '3'];
let y = vec!['a', 'b', 'c'];

现在我想用迭代器来创建一个新的vec,就像['1a', '1b', '1c', '2a', '2b', '2c', '3a', '3b', '3c'],我该怎么做?

a8jjtwal

a8jjtwal1#

最简单的方法是使用itertools机箱中提供的***cartesian product***宏

use itertools::iproduct; // 0.10.1

fn main() {
    let x = vec!['1', '2', '3'];
    let y = vec!['a', 'b', 'c'];
    let product: Vec<String> = iproduct!(x, y)
        .map(|(a, b)| format!("{}{}", a, b))
        .collect();
    println!("{:?}", product);
}

Playground

u5rb5r59

u5rb5r592#

下面是如何使用普通的Rust迭代器来实现这一点:

fn main() {
    let x = vec!['1', '2', '3'];
    let y = vec!['a', 'b', 'c'];
    let product: Vec<String> = x
        .iter()
        .map(|&item_x| y
            .iter()
            .map(move |&item_y| [item_x, item_y]
                .iter()
                .collect()
                )
            )
        .flatten()
        .collect();
    
    println!("{:?}", product);
}

解释

从两个chars构造一个String最简单的方法是在chars上进行collect迭代:

let string: String = [item_x, item_y].iter().collect();

对于x中的每一项,我们迭代y并构造这样的字符串。

x.iter().map(|&item_x| y.iter.map(move |&item_y| ...));

我们使用模式匹配来获取map闭包中的值,而不是引用。由于这一点以及char具有Copy特性的事实,我们可以将moveitem_x转换为内部闭包,从而解决任何生存期问题。
作为上面代码的结果,我们得到了一个String s上迭代器的迭代器。为了扁平化这个迭代器,我们使用flatten方法(谁会想到呢?)。然后我们把扁平化的迭代器收集到结果Vec中。
Playground:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bf2987ed96303a0db0f629884492011e

6psbrbz9

6psbrbz93#

如果你的目标是得到两个迭代器的笛卡尔积,那么现有的答案是有意义的,如果你已经得到了向量或切片(就像最初的问题),你可以做得更好一些:

fn main() {
    let x = vec!['1', '2', '3'];
    let y = vec!['a', 'b', 'c'];
    let result: Vec<String> = product(&x, &y)
        .map(|(a, b)| format!("{}{}", a, b))
        .collect();
    println!("{:?}", result)
}

fn product<'a: 'c, 'b: 'c, 'c, T>(
    a: &'a [T],
    b: &'b [T],
) -> impl Iterator<Item = (&'a T, &'b T)> + 'c {
    (0..a.len())
        .flat_map(|i| (0..b.len()).map(move |j| (i, j)))
        .map(|(i, j)| (&a[i], &b[j]))
}

Playground
任何基于迭代器的解决方案都必须将迭代器的全部内容存储在某个地方,但是如果你已经在向量或数组中存储了数据,你可以使用已知的大小来只存储索引。

相关问题