from itertools import groupby
from operator import itemgetter
from typing import Collection


def partition(pred, iterable):
    """Use a predicate to partition entries into false entries and true entries"""
    # partition(is_odd, range(10)) --> 0 2 4 6 8   and  1 3 5 7 9
    import itertools
    t1, t2 = itertools.tee(iterable)
    return [e for e in t1 if not pred(e)], [e for e in t2 if pred(e)]


def list_to_dict(key_getter=None, list_=None):
    if not key_getter:
        key_getter = id

    if not list_:
        return {}

    return dict((key_getter(elt), elt) for elt in list_)


def paginate(seq, per_page):
    for _, elems in groupby(enumerate(seq), lambda i, _: i // per_page):
        yield list(map(itemgetter(1), elems))


def divide_into_batches(iterable: Collection, by: int = 10):
    index = 0
    count = len(iterable)
    while index < count:
        yield iterable[index:index + by]
        index += by


def pairs_iterator(iterable):
    iterator = iter(iterable)
    prev = None
    for cur in iterator:
        if prev:
            yield prev, cur
        prev = cur
