在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=4
或k=5
答案 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 中的演示。