【问题标题】:How do I use Itertools to create all combinations of a range of Chrono dates?如何使用 Itertools 创建一系列 Chrono 日期的所有组合?
【发布时间】:2019-03-14 23:28:45
【问题描述】:

我正在尝试使用 Rust itertools 生成日期范围的所有组合,但它说不满足特征界限。

extern crate chrono;
extern crate itertools;

use itertools::Itertools;
use chrono::prelude::*;

fn main() {
    let min = NaiveDate::from_ymd(2018, 10, 1);
    let max = NaiveDate::from_ymd(2018, 10, 14);
    let combinations = (min..=max).combinations(5);
}

错误信息:

error[E0599]: no method named `combinations` found for type `std::ops::RangeInclusive<chrono::NaiveDate>` in the current scope
  --> src/main.rs:46:36
   |
46 |     let combinations = (min..=max).combinations(5);
   |                                    ^^^^^^^^^^^^
   |
   = note: the method `combinations` exists but the following trait bounds were not satisfied:
           `std::ops::RangeInclusive<chrono::NaiveDate> : itertools::Itertools`
           `&std::ops::RangeInclusive<chrono::NaiveDate> : itertools::Itertools`
           `&mut std::ops::RangeInclusive<chrono::NaiveDate> : itertools::Itertools`

我希望 Itertools 是为通用 RangeInclusive 实现的。我正在学习 Rust,所以我可能会遗漏一些明显的东西。

【问题讨论】:

  • 问题的根本原因是chrono 没有实现Iterator 的日期类型范围。
  • 我明白了,itertools 不是为范围实现的,它们是为Iterator 实现的,这对于一个范围来说并不总是可能的(例如,Range&lt;f32&gt;)但它可能是可能的对于Range&lt;NaiveDate&gt; 但chrono 没有实现它。
  • 这样组合的结果是什么?
  • 它是一个数学组合的迭代器,是迭代器给定大小元素的子集。我不知道你为什么需要它来约会。另一方面,简单的日期范围对日历非常有用。

标签: rust


【解决方案1】:

Itertools,顾名思义,适用于 Iterators。 not possible 在稳定的 Rust(版本 1.29)中从标准库之外创建一个类型的可迭代范围。

相反,我们可以为日期范围创建自定义迭代器,基于looping over dates

extern crate chrono; // 0.4.6
extern crate itertools; // 0.7.8

use chrono::{Duration, NaiveDate};
use itertools::Itertools;
use std::mem;

struct DateRange(NaiveDate, NaiveDate);

impl Iterator for DateRange {
    type Item = NaiveDate;
    fn next(&mut self) -> Option<Self::Item> {
        if self.0 < self.1 {
            let next = self.0 + Duration::days(1);
            Some(mem::replace(&mut self.0, next))
        } else {
            None
        }
    }
}

fn main() {
    let min = NaiveDate::from_ymd(2018, 10, 1);
    let max = NaiveDate::from_ymd(2018, 10, 14);
    let combinations: Vec<_> = DateRange(min, max).combinations(5).collect();
    println!("{:?}", combinations)
}

【讨论】:

  • 正式的孤儿规则在一致性 RFC 1023 中:github.com/rust-lang/rfcs/blob/master/text/…(我希望我没有错过任何更新。Rust 确实需要在单个文档中使用正式的语言定义,并与版本保持同步.)
  • @starblue 我不清楚你为什么在这里提出连贯性。一个 crate 产生一个可迭代的范围是完全一致的,但关键特征是不稳定的。
  • 我想检查为什么 chrono 板条箱不能为标准范围类型构造函数实现 Iterator 特征。在所有新定义的日期类型NaiveDate 出现之后,但在Range 类型构造函数的下方。但事实上,如果您应用不足以允许它的正式规则。我放置链接是因为通过搜索很难找到 RFC,因为关于修改孤立规则以允许更多内容的讨论非常混乱。
  • @starblue 我明白了。是的,标准库implements Iterator for Range&lt;A: Step&gt;,所以一个板条箱可能不会为Range&lt;NaiveDate&gt; 定义Iterator。但是,它可以为NaiveDate实现Step,只是Step不稳定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多