在Rust中,在itertools.product中复制Python的“repeat”参数的正确方法是什么?

时间:2017-05-23 15:46:00

标签: python rust itertools

在Python中,我可以这样做:

from itertools import product

k = 3
for kmer in product("AGTC", repeat=k):
    print(kmer)

在Rust中,我可以强制k=3的行为:

#[macro_use] extern crate itertools;

for kmer in iproduct!("AGTC".chars(), "AGTC".chars(), "AGTC".chars()){
    println!("{:?}", kmer);
}

但如果我想要k=4k=5

,该怎么办?

2 个答案:

答案 0 :(得分:3)

为任何k编写任何类型的适当泛化都很难,因为返回类型可能是任何大小的元组。由于您只想在String上工作,因此更容易:playground

fn kproduct(seq: String, k: u32) -> Vec<String> {
    match k {
        0 => vec![],
        1 => seq.chars().map(|c| c.to_string()).collect(),
        2 => iproduct!(seq.chars(), seq.chars()).map(|(a, b)| format!("{}{}", a, b)).collect(),
        _ => iproduct!(kproduct(seq.clone(), k - 1), seq.chars()).map(|(a, b)| format!("{}{}", a, b)).collect(),
    }
}

答案 1 :(得分:1)

我在 4 年后回答这个问题是因为接受的答案太复杂了,而且由于 Python 的 itertools.product 是一个通用函数(而接受的答案仅适用于 String s)。 此外,请注意在接受的答案中定义的 kproduct 函数是递归的,并且 Rust doesn't guarantee tail-call optimization

使用第三方 itertools crate,我们可以通过两种方式定义 product_repeat 函数:通过定义一个标准的顶级函数,或者通过为所有ProductRepeat

这是顶级函数:

Iterator

如果你更喜欢增加 Iterator trait,你可以这样做:

use itertools::{Itertools, MultiProduct};

/// Rust version of Python's itertools.product().
/// It returns the cartesian product of the input iterables, and it is
/// semantically equivalent to `repeat` nested for loops.
///
/// # Arguments
///
/// * `it` - An iterator over a cloneable data structure
/// * `repeat` - Number of repetitions of the given iterator
pub fn product_repeat<I>(it: I, repeat: usize) -> MultiProduct<I>
  where
    I: Iterator + Clone,
    I::Item: Clone {
  std::iter::repeat(it)
    .take(repeat)
    .multi_cartesian_product()
}

这是 Rust playground 中的演示。