Вспомогательный признак для выделения итератор цепей, которые включают элементы группировки в кортежи


В itertools::Itertools::tuples способ от itertools обрешетка, как представляется, только в том аспекте, что черта TupleCollect в Bound T: TupleCollect, который реализуется за однородные кортежей размеры от 1 до 4, частная. В приведенном ниже примере параметр (i32, i32) для F не может быть заменено какой-нибудь универсального типа, который позволит картографа функции для кортежей произвольной размерности.

fn parse<I, F, C>(elems: I, mapper: F) -> C
    where
        I: IntoIterator<Item=i32>,
        F: Fn((i32, i32)) -> i32,
        C: FromIterator<i32>,
{
    elems.into_iter()
        .map(|i| i+i) // before mapping tuples
        .tuples()
        .map(mapper)
        .map(|i| i*i) // after mapping tuples
        .collect()
}

По моему решение этой проблемы, я ввожу помощника черта (TupleIterItem), которое реализуется за однородные кортежей размеры от 1 до 4. Он содержит map метод, который конкретно абстрагирует карте операции на итераторы кортежей. Альтернатива tuples способ более универсален и предназначен для обслуживания произвольный итератор операций.

extern crate itertools;

mod tuple_iter{
    use itertools::Itertools;

    pub trait TupleIterItem<'a> {
        type Item;

        fn tuples<'b: 'a, I: 'a, F: 'b, R>(F, I) -> R
            where
                I: IntoIterator<Item = Self::Item>,
                F: Fn(Box<Iterator<Item = Self> + 'a>) -> R;

        fn map<'b: 'a, I: 'a, F: 'b, R>(F, I) -> Box<Iterator<Item = R> + 'a>
            where
                I: IntoIterator<Item = Self::Item>,
                F: Fn(Self) -> R,
                Self: Sized;
    }

    macro_rules! impl_tuple_mapper {
        () => ();
        ($A:ident; $($X:ident),*) => (
            impl<'a, $A: 'a> TupleIterItem<'a> for ($($X),*,){
                type Item=$A;

                fn tuples<'b: 'a, I: 'a, F: 'b, R>(iter_mapper: F, i: I) ->  R
                    where I: IntoIterator<Item=Self::Item>,
                          F: Fn(Box<Iterator<Item=Self> + 'a>) -> R
                {
                    iter_mapper(Box::new(i.into_iter().tuples::<Self>()))
                }

                fn map<'b: 'a, I: 'a, F: 'b, R>(mapper: F, i: I) ->  Box<Iterator<Item=R> + 'a>
                    where I: IntoIterator<Item=Self::Item>,
                          F: Fn(Self) -> R
                {
                    Box::new(i.into_iter().tuples().map(mapper))
                }
            }
        );
    }

    impl_tuple_mapper!(A; A);
    impl_tuple_mapper!(A; A, A);
    impl_tuple_mapper!(A; A, A, A);
    impl_tuple_mapper!(A; A, A, A, A);
}

// ----------- demonstration ------------
use itertools::Itertools;
use std::iter::FromIterator;
use tuple_iter::TupleIterItem;
use std::fmt::UpperHex;

fn parse_to_hex<'a, 'b: 'a, I: 'a, T, L, F: 'a, C>(
        elems: I,
        mapper: F,
        nt: usize
    ) -> C
    where
        I: IntoIterator<Item=&'b str>,
        T: TupleIterItem<'a, Item=usize>,
        L: UpperHex,
        F: Fn(T) -> L,
        C: FromIterator<String>,
{
    let elems_pre = elems.into_iter().map(|s| s.len()); // before mapping tuples
    T::map(mapper, elems_pre)
        .map(|i| format!("{:X}", i)) // after mapping tuples
        .take(nt) 
        .collect()
}

fn parse_to_hex_generic<'a, 'b: 'a, I: 'a, T, L, O, F: 'a, C>(
        elems: I,
        mapper: F,
        nt: usize
    ) -> C
    where
        I: IntoIterator<Item=&'b str>,
        T: TupleIterItem<'a, Item=usize>,
        L: UpperHex,
        O: IntoIterator<Item=L>,
        F: Fn(Box<Iterator<Item=T> + 'a>) -> O,
        C: FromIterator<String>,
{
    let elems_pre = elems
        .into_iter()
        .map(|s| s.len()); // before mapping tuples
    T::tuples(mapper, elems_pre)
        .into_iter()
        .map(|i| format!("{:X}", i)) // after mapping tuples
        .take(nt)
        .collect()
}

fn main(){
    let code = "aa bbbb ccccc ddd eeee ff
        aaaaa bbbbb cccccccccc ddd
        efghij kl xxx xxxxx mn opqrstu
        1234 5678 910111 21314 15 16171819 xxxx xxxxx xxxx";

    let mut elems = code.split_whitespace();

    let hex: Vec<_> = parse_to_hex(elems.by_ref(), |(a, b, c)| a * b + c, 2);
    let hex2: Vec<_> = parse_to_hex(elems.by_ref(), |(a, b)| a + b, 2);
    let hex3: Vec<_> = parse_to_hex_generic(
        elems.by_ref(),
        |tuples| {
            tuples
                .unique_by(|&(a, b)| a + b)
                .map(|(a, b)| a * b - a / (b * 2))
        },
        2,
    );
    let hex4: Vec<_> = parse_to_hex_generic(
        elems.by_ref(),
        |tuples| {
            tuples
                .unique_by(|&(a, b, c)| a * b * c)
                .map(|(a, b, c)| a + b + c)
        },
        3,
    );

    //["D", "E"] ["A", "D"] ["B", "E"] ["E", "F"]
    println!("{:?} {:?} {:?} {:?}", hex, hex2, hex3, hex4);
}

Моя главная забота-ли я с видом тривиальное решение этой проблемы. Кроме того, я не удивлюсь, если мое решение имеет конструктивные недостатки и может быть улучшена, чтобы быть более идиоматические и элегантно.



253
3
задан 27 марта 2018 в 07:03 Источник Поделиться
Комментарии