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

nc1teljy  于 2022-11-21  发布在  Python
关注(0)|答案(2)|浏览(116)

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

ggazkfy8

ggazkfy81#

为任意类型的任意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(),
    }
}
n53p2ov0

n53p2ov02#

我在4年后才回答这个问题,一方面是因为公认的答案太复杂了,另一方面是因为Python的itertools.product是一个泛型函数(而公认的答案只对String有效)。此外,请注意,公认答案中定义的kproduct函数是递归的,Rust doesn't guarantee tail-call optimization
使用第三方itertools机箱,我们可以通过两种方式定义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()
}

如果您更喜欢增加Iterator特性,可以按如下方式进行:

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 playground中的一个演示。

相关问题