Python: itertools

 

groupby:

import typing, operator, itertools


class GroupBy:
    def __init__(self, iterable: typing.Iterable, key=None):
        if key is None:
            key = lambda v: v
        self.key = key
        self.it = iter(iterable)
        self.current_key = self.target_key = self.current_value = object()

    def __iter__(self):
        return self

    def __next__(self):
        self.id = object()
        while self.current_key == self.target_key:  # advance to next group
            self.current_value = next(self.it)  # exit on StopIteration
            self.current_key = self.key(self.current_value)
        self.target_key = self.current_key  # pass to _grouper, mark the end
        return self.current_key, self._grouper(self.target_key, self.id)

    def _grouper(self, target_key, id):
        while self.id is id and self.current_key == self.target_key:
            yield self.current_value
            try:
                self.current_value = next(self.it)
            except StopIteration:
                return
            self.current_key = self.key(self.current_value)


it = GroupBy('AAaABBBCCDAABBB')
for k, g in it:
    print(k, list(g))
print('~' * 80)
it = GroupBy('AAaABBBCCDAABBB', key=lambda v: v.upper())
for k, g in it:
    print(k, list(g))
print('~' * 80)
it = GroupBy(sorted('AAaABBBCCDAABBB', key=lambda v: v.upper()), key=lambda v: v.upper())
for k, g in it:
    print(k, list(g))

 

islice:

import sys
import typing, operator, itertools


def islice(iterable, *args):
    s = slice(*args)
    start, stop, step = s.start or 0, s.stop or sys.maxsize, s.step or 1
    it = iter(range(start, stop, step))

    try:
        nexti = next(it)
    except StopIteration:
        # consume iterable up to the start position
        for i, element in zip(range(start), iterable):
            pass
        return
    try:
        for i, element in enumerate(iterable):
            if i == nexti:
                yield element
                nexti = next(it)
    except StopIteration:  # only next(it) can trigger StopIteration
        # consume gap between i & stop, because step > 1
        for i, element in zip(range(i + 1, stop), iterable):
            pass


islice(None, 2, None)

 

pairwise, triplewise, quadwise, sliding_window

import collections
import itertools, typing
import operator


def pairwise(iterable):
    a, b = itertools.tee(iterable, 2)
    next(b, None)
    return zip(a, b)


print(list(pairwise('abcd')))


def tripewise(iterable):
    for (a, _), (b, c) in pairwise(pairwise(iterable)):
        yield a, b, c


print(list(tripewise('abcd')))


def quadwise(iterable):
    for (a, _, _), (b, c, d) in pairwise(tripewise(iterable)):
        yield a, b, c, d


print(list(quadwise('abcdef')))


def sliding_window(iterable, n):
    it = iter(iterable)
    deque = collections.deque(itertools.islice(it, n), maxlen=n)
    if len(deque) == n:
        yield tuple(deque)

    for v in it:
        deque.append(v)
        yield tuple(deque)


print(list(sliding_window('abcdef', 4)))

 

posted @ 2022-10-10 13:41  ascertain  阅读(43)  评论(0)    收藏  举报