如何使用迭代器获得 2 个向量的笛卡尔积?

abc*_*abc 4 rust

我有 2Vec个:

let x = vec!['1', '2', '3'];
let y = vec!['a', 'b', 'c'];
Run Code Online (Sandbox Code Playgroud)

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

Net*_*ave 14

最简单的方法是使用板条箱中提供的笛卡尔积宏itertools

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);
}
Run Code Online (Sandbox Code Playgroud)

操场


Max*_*nko 7

以下是如何使用普通 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);
}
Run Code Online (Sandbox Code Playgroud)

解释

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

let string: String = [item_x, item_y].iter().collect();
Run Code Online (Sandbox Code Playgroud)

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

x.iter().map(|&item_x| y.iter.map(move |&item_y| ...));
Run Code Online (Sandbox Code Playgroud)

我们使用模式匹配来获取map闭包中的值而不是引用。正因为如此,而且事实是charCopy我们可以move item_x进入内部封闭,解决任何一生的问题。

作为上面代码的结果,我们得到了一个对Strings 的迭代器的迭代器。为了展平该迭代器,我们使用flatten方法(谁会想到?)。然后我们将平面迭代器收集到结果中Vec

游乐场:https://play.rust-lang.org/?version=stable&mode =debug&edition=2018&gist=bf2987ed96303a0db0f629884492011e


Jul*_*ian 5

如果您的目标是获得两个迭代器的笛卡尔积,则现有答案是有意义的。如果你已经有了向量或切片(就像原来的问题一样),你可以做得更好一点:

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>(
    xs: &'a [T],
    ys: &'b [T],
) -> impl Iterator<Item = (&'a T, &'b T)> + 'c {
    xs.iter().flat_map(move |x| std::iter::repeat(x).zip(ys))
}
Run Code Online (Sandbox Code Playgroud)

操场

任何基于迭代器的解决方案都必然需要将迭代器的完整内容存储在某处,但如果您已经在向量或数组中拥有数据,则可以使用已知的大小来仅存储索引。