【问题标题】:In Rust, what is the proper way to replicate Python's "repeat" parameter in itertools.product?在 Rust 中,在 itertools.product 中复制 Python 的“repeat”参数的正确方法是什么?
【发布时间】:2017-05-23 15:46:00
【问题描述】:

在 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,您无法生成 k 值的 Rust 元组。
  • 我不一定需要元组;字符串会更好。我最终会为这些 kmers 搜索更长的字符串。

标签: python rust itertools


【解决方案1】:

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

【讨论】:

  • 这正是我想要完成的;谢谢!
【解决方案2】:

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

使用第三方itertools crate,我们可以通过两种方式定义product_repeat 函数:定义标准顶级函数,或者为所有Iterators 添加ProductRepeat 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()
}

如果您更喜欢增加 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中的演示。

【讨论】:

    猜你喜欢
    • 2017-09-28
    • 2020-09-14
    • 2021-08-23
    • 2014-08-23
    • 1970-01-01
    • 2019-01-20
    • 2014-02-17
    • 2013-03-02
    相关资源
    最近更新 更多