Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use Itertools to create all combinations of a range of Chrono dates?

Tags:

rust

I'm trying to generate all combinations of a date range using Rust itertools but it says that trait bounds were not satisfied.

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

The error message:

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`

I would expect that Itertools were implemented for generic RangeInclusive. I am learning Rust so I might be missing something obvious.

like image 454
JoeCamel Avatar asked Oct 10 '18 06:10

JoeCamel


People also ask

How does Itertools combinations work?

The itertools. combinations() function takes two arguments—an iterable inputs and a positive integer n —and produces an iterator over tuples of all combinations of n elements in inputs .

What does Itertools combinations return?

What does itertools. combinations() do ? It returns r length subsequences of elements from the input iterable. Combinations are emitted in lexicographic sort order.

How do you implement a combination in Python?

To create combinations without using itertools, iterate the list one by one and fix the first element of the list and make combinations with the remaining list. Similarly, iterate with all the list elements one by one by recursion of the remaining list.


1 Answers

Itertools, as the name suggests, works on Iterators. It is not possible to create an iterable range of a type from outside of the standard library in stable Rust (version 1.29).

Instead, we can create a custom iterator for a date range, based on 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)
}
  • Iterating over a range of generic type
  • Loop over date range
like image 180
Shepmaster Avatar answered Nov 11 '22 00:11

Shepmaster