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



在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呢?

任何 k 编写任何类型的正确泛化都很难,因为返回类型可以是任何大小的元组。由于您只想在String上工作,因此很容易: 游乐场

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(),
    }
}

我在 4 年后回答这个问题,因为接受的答案太复杂了,而且因为 Python 的itertools.product是一个通用函数(而接受的答案仅适用于 String s(。此外,请注意,在接受的答案中定义的kproduct函数是递归的,并且 Rust 不保证尾调用优化。

使用第三方 itertools crate,我们可以通过两种方式定义product_repeat函数:要么通过定义一个标准的顶级函数,要么为所有Iterator添加一个ProductRepeat特征。

这是顶级函数:

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()
}

如果您更喜欢增强迭代器特征,则可以执行以下操作:

pub trait ProductRepeat: Iterator + Clone
  where Self::Item: Clone {
  fn product_repeat(self, repeat: usize) -> MultiProduct<Self> {
    std::iter::repeat(self)
      .take(repeat)
      .multi_cartesian_product()
  }
}
impl<T: Iterator + Clone> ProductRepeat for T
  where T::Item: Clone {}

这是 Rust 操场上的一个演示。

相关内容

  • 没有找到相关文章

最新更新