17db96d56Sopenharmony_ci:mod:`itertools` --- Functions creating iterators for efficient looping 27db96d56Sopenharmony_ci======================================================================= 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci.. module:: itertools 57db96d56Sopenharmony_ci :synopsis: Functions creating iterators for efficient looping. 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci.. moduleauthor:: Raymond Hettinger <python@rcn.com> 87db96d56Sopenharmony_ci.. sectionauthor:: Raymond Hettinger <python@rcn.com> 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci.. testsetup:: 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ci from itertools import * 137db96d56Sopenharmony_ci import collections 147db96d56Sopenharmony_ci import math 157db96d56Sopenharmony_ci import operator 167db96d56Sopenharmony_ci import random 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ci-------------- 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ciThis module implements a number of :term:`iterator` building blocks inspired 217db96d56Sopenharmony_ciby constructs from APL, Haskell, and SML. Each has been recast in a form 227db96d56Sopenharmony_cisuitable for Python. 237db96d56Sopenharmony_ci 247db96d56Sopenharmony_ciThe module standardizes a core set of fast, memory efficient tools that are 257db96d56Sopenharmony_ciuseful by themselves or in combination. Together, they form an "iterator 267db96d56Sopenharmony_cialgebra" making it possible to construct specialized tools succinctly and 277db96d56Sopenharmony_ciefficiently in pure Python. 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ciFor instance, SML provides a tabulation tool: ``tabulate(f)`` which produces a 307db96d56Sopenharmony_cisequence ``f(0), f(1), ...``. The same effect can be achieved in Python 317db96d56Sopenharmony_ciby combining :func:`map` and :func:`count` to form ``map(f, count())``. 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ciThese tools and their built-in counterparts also work well with the high-speed 347db96d56Sopenharmony_cifunctions in the :mod:`operator` module. For example, the multiplication 357db96d56Sopenharmony_cioperator can be mapped across two vectors to form an efficient dot-product: 367db96d56Sopenharmony_ci``sum(starmap(operator.mul, zip(vec1, vec2, strict=True)))``. 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci**Infinite iterators:** 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci================== ================= ================================================= ========================================= 427db96d56Sopenharmony_ciIterator Arguments Results Example 437db96d56Sopenharmony_ci================== ================= ================================================= ========================================= 447db96d56Sopenharmony_ci:func:`count` start, [step] start, start+step, start+2*step, ... ``count(10) --> 10 11 12 13 14 ...`` 457db96d56Sopenharmony_ci:func:`cycle` p p0, p1, ... plast, p0, p1, ... ``cycle('ABCD') --> A B C D A B C D ...`` 467db96d56Sopenharmony_ci:func:`repeat` elem [,n] elem, elem, elem, ... endlessly or up to n times ``repeat(10, 3) --> 10 10 10`` 477db96d56Sopenharmony_ci================== ================= ================================================= ========================================= 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci**Iterators terminating on the shortest input sequence:** 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci============================ ============================ ================================================= ============================================================= 527db96d56Sopenharmony_ciIterator Arguments Results Example 537db96d56Sopenharmony_ci============================ ============================ ================================================= ============================================================= 547db96d56Sopenharmony_ci:func:`accumulate` p [,func] p0, p0+p1, p0+p1+p2, ... ``accumulate([1,2,3,4,5]) --> 1 3 6 10 15`` 557db96d56Sopenharmony_ci:func:`chain` p, q, ... p0, p1, ... plast, q0, q1, ... ``chain('ABC', 'DEF') --> A B C D E F`` 567db96d56Sopenharmony_ci:func:`chain.from_iterable` iterable p0, p1, ... plast, q0, q1, ... ``chain.from_iterable(['ABC', 'DEF']) --> A B C D E F`` 577db96d56Sopenharmony_ci:func:`compress` data, selectors (d[0] if s[0]), (d[1] if s[1]), ... ``compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F`` 587db96d56Sopenharmony_ci:func:`dropwhile` pred, seq seq[n], seq[n+1], starting when pred fails ``dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1`` 597db96d56Sopenharmony_ci:func:`filterfalse` pred, seq elements of seq where pred(elem) is false ``filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8`` 607db96d56Sopenharmony_ci:func:`groupby` iterable[, key] sub-iterators grouped by value of key(v) 617db96d56Sopenharmony_ci:func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] ``islice('ABCDEFG', 2, None) --> C D E F G`` 627db96d56Sopenharmony_ci:func:`pairwise` iterable (p[0], p[1]), (p[1], p[2]) ``pairwise('ABCDEFG') --> AB BC CD DE EF FG`` 637db96d56Sopenharmony_ci:func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... ``starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000`` 647db96d56Sopenharmony_ci:func:`takewhile` pred, seq seq[0], seq[1], until pred fails ``takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4`` 657db96d56Sopenharmony_ci:func:`tee` it, n it1, it2, ... itn splits one iterator into n 667db96d56Sopenharmony_ci:func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-`` 677db96d56Sopenharmony_ci============================ ============================ ================================================= ============================================================= 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci**Combinatoric iterators:** 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci============================================== ==================== ============================================================= 727db96d56Sopenharmony_ciIterator Arguments Results 737db96d56Sopenharmony_ci============================================== ==================== ============================================================= 747db96d56Sopenharmony_ci:func:`product` p, q, ... [repeat=1] cartesian product, equivalent to a nested for-loop 757db96d56Sopenharmony_ci:func:`permutations` p[, r] r-length tuples, all possible orderings, no repeated elements 767db96d56Sopenharmony_ci:func:`combinations` p, r r-length tuples, in sorted order, no repeated elements 777db96d56Sopenharmony_ci:func:`combinations_with_replacement` p, r r-length tuples, in sorted order, with repeated elements 787db96d56Sopenharmony_ci============================================== ==================== ============================================================= 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci============================================== ============================================================= 817db96d56Sopenharmony_ciExamples Results 827db96d56Sopenharmony_ci============================================== ============================================================= 837db96d56Sopenharmony_ci``product('ABCD', repeat=2)`` ``AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD`` 847db96d56Sopenharmony_ci``permutations('ABCD', 2)`` ``AB AC AD BA BC BD CA CB CD DA DB DC`` 857db96d56Sopenharmony_ci``combinations('ABCD', 2)`` ``AB AC AD BC BD CD`` 867db96d56Sopenharmony_ci``combinations_with_replacement('ABCD', 2)`` ``AA AB AC AD BB BC BD CC CD DD`` 877db96d56Sopenharmony_ci============================================== ============================================================= 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci.. _itertools-functions: 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ciItertool functions 937db96d56Sopenharmony_ci------------------ 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_ciThe following module functions all construct and return iterators. Some provide 967db96d56Sopenharmony_cistreams of infinite length, so they should only be accessed by functions or 977db96d56Sopenharmony_ciloops that truncate the stream. 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci.. function:: accumulate(iterable[, func, *, initial=None]) 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci Make an iterator that returns accumulated sums, or accumulated 1027db96d56Sopenharmony_ci results of other binary functions (specified via the optional 1037db96d56Sopenharmony_ci *func* argument). 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci If *func* is supplied, it should be a function 1067db96d56Sopenharmony_ci of two arguments. Elements of the input *iterable* may be any type 1077db96d56Sopenharmony_ci that can be accepted as arguments to *func*. (For example, with 1087db96d56Sopenharmony_ci the default operation of addition, elements may be any addable 1097db96d56Sopenharmony_ci type including :class:`~decimal.Decimal` or 1107db96d56Sopenharmony_ci :class:`~fractions.Fraction`.) 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci Usually, the number of elements output matches the input iterable. 1137db96d56Sopenharmony_ci However, if the keyword argument *initial* is provided, the 1147db96d56Sopenharmony_ci accumulation leads off with the *initial* value so that the output 1157db96d56Sopenharmony_ci has one more element than the input iterable. 1167db96d56Sopenharmony_ci 1177db96d56Sopenharmony_ci Roughly equivalent to:: 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci def accumulate(iterable, func=operator.add, *, initial=None): 1207db96d56Sopenharmony_ci 'Return running totals' 1217db96d56Sopenharmony_ci # accumulate([1,2,3,4,5]) --> 1 3 6 10 15 1227db96d56Sopenharmony_ci # accumulate([1,2,3,4,5], initial=100) --> 100 101 103 106 110 115 1237db96d56Sopenharmony_ci # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120 1247db96d56Sopenharmony_ci it = iter(iterable) 1257db96d56Sopenharmony_ci total = initial 1267db96d56Sopenharmony_ci if initial is None: 1277db96d56Sopenharmony_ci try: 1287db96d56Sopenharmony_ci total = next(it) 1297db96d56Sopenharmony_ci except StopIteration: 1307db96d56Sopenharmony_ci return 1317db96d56Sopenharmony_ci yield total 1327db96d56Sopenharmony_ci for element in it: 1337db96d56Sopenharmony_ci total = func(total, element) 1347db96d56Sopenharmony_ci yield total 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ci There are a number of uses for the *func* argument. It can be set to 1377db96d56Sopenharmony_ci :func:`min` for a running minimum, :func:`max` for a running maximum, or 1387db96d56Sopenharmony_ci :func:`operator.mul` for a running product. Amortization tables can be 1397db96d56Sopenharmony_ci built by accumulating interest and applying payments: 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ci .. doctest:: 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ci >>> data = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8] 1447db96d56Sopenharmony_ci >>> list(accumulate(data, operator.mul)) # running product 1457db96d56Sopenharmony_ci [3, 12, 72, 144, 144, 1296, 0, 0, 0, 0] 1467db96d56Sopenharmony_ci >>> list(accumulate(data, max)) # running maximum 1477db96d56Sopenharmony_ci [3, 4, 6, 6, 6, 9, 9, 9, 9, 9] 1487db96d56Sopenharmony_ci 1497db96d56Sopenharmony_ci # Amortize a 5% loan of 1000 with 4 annual payments of 90 1507db96d56Sopenharmony_ci >>> cashflows = [1000, -90, -90, -90, -90] 1517db96d56Sopenharmony_ci >>> list(accumulate(cashflows, lambda bal, pmt: bal*1.05 + pmt)) 1527db96d56Sopenharmony_ci [1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001] 1537db96d56Sopenharmony_ci 1547db96d56Sopenharmony_ci See :func:`functools.reduce` for a similar function that returns only the 1557db96d56Sopenharmony_ci final accumulated value. 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_ci .. versionadded:: 3.2 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci .. versionchanged:: 3.3 1607db96d56Sopenharmony_ci Added the optional *func* parameter. 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci .. versionchanged:: 3.8 1637db96d56Sopenharmony_ci Added the optional *initial* parameter. 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci.. function:: chain(*iterables) 1667db96d56Sopenharmony_ci 1677db96d56Sopenharmony_ci Make an iterator that returns elements from the first iterable until it is 1687db96d56Sopenharmony_ci exhausted, then proceeds to the next iterable, until all of the iterables are 1697db96d56Sopenharmony_ci exhausted. Used for treating consecutive sequences as a single sequence. 1707db96d56Sopenharmony_ci Roughly equivalent to:: 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ci def chain(*iterables): 1737db96d56Sopenharmony_ci # chain('ABC', 'DEF') --> A B C D E F 1747db96d56Sopenharmony_ci for it in iterables: 1757db96d56Sopenharmony_ci for element in it: 1767db96d56Sopenharmony_ci yield element 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci 1797db96d56Sopenharmony_ci.. classmethod:: chain.from_iterable(iterable) 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci Alternate constructor for :func:`chain`. Gets chained inputs from a 1827db96d56Sopenharmony_ci single iterable argument that is evaluated lazily. Roughly equivalent to:: 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ci def from_iterable(iterables): 1857db96d56Sopenharmony_ci # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F 1867db96d56Sopenharmony_ci for it in iterables: 1877db96d56Sopenharmony_ci for element in it: 1887db96d56Sopenharmony_ci yield element 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci.. function:: combinations(iterable, r) 1927db96d56Sopenharmony_ci 1937db96d56Sopenharmony_ci Return *r* length subsequences of elements from the input *iterable*. 1947db96d56Sopenharmony_ci 1957db96d56Sopenharmony_ci The combination tuples are emitted in lexicographic ordering according to 1967db96d56Sopenharmony_ci the order of the input *iterable*. So, if the input *iterable* is sorted, 1977db96d56Sopenharmony_ci the output tuples will be produced in sorted order. 1987db96d56Sopenharmony_ci 1997db96d56Sopenharmony_ci Elements are treated as unique based on their position, not on their 2007db96d56Sopenharmony_ci value. So if the input elements are unique, there will be no repeated 2017db96d56Sopenharmony_ci values in each combination. 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci Roughly equivalent to:: 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci def combinations(iterable, r): 2067db96d56Sopenharmony_ci # combinations('ABCD', 2) --> AB AC AD BC BD CD 2077db96d56Sopenharmony_ci # combinations(range(4), 3) --> 012 013 023 123 2087db96d56Sopenharmony_ci pool = tuple(iterable) 2097db96d56Sopenharmony_ci n = len(pool) 2107db96d56Sopenharmony_ci if r > n: 2117db96d56Sopenharmony_ci return 2127db96d56Sopenharmony_ci indices = list(range(r)) 2137db96d56Sopenharmony_ci yield tuple(pool[i] for i in indices) 2147db96d56Sopenharmony_ci while True: 2157db96d56Sopenharmony_ci for i in reversed(range(r)): 2167db96d56Sopenharmony_ci if indices[i] != i + n - r: 2177db96d56Sopenharmony_ci break 2187db96d56Sopenharmony_ci else: 2197db96d56Sopenharmony_ci return 2207db96d56Sopenharmony_ci indices[i] += 1 2217db96d56Sopenharmony_ci for j in range(i+1, r): 2227db96d56Sopenharmony_ci indices[j] = indices[j-1] + 1 2237db96d56Sopenharmony_ci yield tuple(pool[i] for i in indices) 2247db96d56Sopenharmony_ci 2257db96d56Sopenharmony_ci The code for :func:`combinations` can be also expressed as a subsequence 2267db96d56Sopenharmony_ci of :func:`permutations` after filtering entries where the elements are not 2277db96d56Sopenharmony_ci in sorted order (according to their position in the input pool):: 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci def combinations(iterable, r): 2307db96d56Sopenharmony_ci pool = tuple(iterable) 2317db96d56Sopenharmony_ci n = len(pool) 2327db96d56Sopenharmony_ci for indices in permutations(range(n), r): 2337db96d56Sopenharmony_ci if sorted(indices) == list(indices): 2347db96d56Sopenharmony_ci yield tuple(pool[i] for i in indices) 2357db96d56Sopenharmony_ci 2367db96d56Sopenharmony_ci The number of items returned is ``n! / r! / (n-r)!`` when ``0 <= r <= n`` 2377db96d56Sopenharmony_ci or zero when ``r > n``. 2387db96d56Sopenharmony_ci 2397db96d56Sopenharmony_ci.. function:: combinations_with_replacement(iterable, r) 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_ci Return *r* length subsequences of elements from the input *iterable* 2427db96d56Sopenharmony_ci allowing individual elements to be repeated more than once. 2437db96d56Sopenharmony_ci 2447db96d56Sopenharmony_ci The combination tuples are emitted in lexicographic ordering according to 2457db96d56Sopenharmony_ci the order of the input *iterable*. So, if the input *iterable* is sorted, 2467db96d56Sopenharmony_ci the output tuples will be produced in sorted order. 2477db96d56Sopenharmony_ci 2487db96d56Sopenharmony_ci Elements are treated as unique based on their position, not on their 2497db96d56Sopenharmony_ci value. So if the input elements are unique, the generated combinations 2507db96d56Sopenharmony_ci will also be unique. 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_ci Roughly equivalent to:: 2537db96d56Sopenharmony_ci 2547db96d56Sopenharmony_ci def combinations_with_replacement(iterable, r): 2557db96d56Sopenharmony_ci # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC 2567db96d56Sopenharmony_ci pool = tuple(iterable) 2577db96d56Sopenharmony_ci n = len(pool) 2587db96d56Sopenharmony_ci if not n and r: 2597db96d56Sopenharmony_ci return 2607db96d56Sopenharmony_ci indices = [0] * r 2617db96d56Sopenharmony_ci yield tuple(pool[i] for i in indices) 2627db96d56Sopenharmony_ci while True: 2637db96d56Sopenharmony_ci for i in reversed(range(r)): 2647db96d56Sopenharmony_ci if indices[i] != n - 1: 2657db96d56Sopenharmony_ci break 2667db96d56Sopenharmony_ci else: 2677db96d56Sopenharmony_ci return 2687db96d56Sopenharmony_ci indices[i:] = [indices[i] + 1] * (r - i) 2697db96d56Sopenharmony_ci yield tuple(pool[i] for i in indices) 2707db96d56Sopenharmony_ci 2717db96d56Sopenharmony_ci The code for :func:`combinations_with_replacement` can be also expressed as 2727db96d56Sopenharmony_ci a subsequence of :func:`product` after filtering entries where the elements 2737db96d56Sopenharmony_ci are not in sorted order (according to their position in the input pool):: 2747db96d56Sopenharmony_ci 2757db96d56Sopenharmony_ci def combinations_with_replacement(iterable, r): 2767db96d56Sopenharmony_ci pool = tuple(iterable) 2777db96d56Sopenharmony_ci n = len(pool) 2787db96d56Sopenharmony_ci for indices in product(range(n), repeat=r): 2797db96d56Sopenharmony_ci if sorted(indices) == list(indices): 2807db96d56Sopenharmony_ci yield tuple(pool[i] for i in indices) 2817db96d56Sopenharmony_ci 2827db96d56Sopenharmony_ci The number of items returned is ``(n+r-1)! / r! / (n-1)!`` when ``n > 0``. 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ci .. versionadded:: 3.1 2857db96d56Sopenharmony_ci 2867db96d56Sopenharmony_ci 2877db96d56Sopenharmony_ci.. function:: compress(data, selectors) 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci Make an iterator that filters elements from *data* returning only those that 2907db96d56Sopenharmony_ci have a corresponding element in *selectors* that evaluates to ``True``. 2917db96d56Sopenharmony_ci Stops when either the *data* or *selectors* iterables has been exhausted. 2927db96d56Sopenharmony_ci Roughly equivalent to:: 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci def compress(data, selectors): 2957db96d56Sopenharmony_ci # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F 2967db96d56Sopenharmony_ci return (d for d, s in zip(data, selectors) if s) 2977db96d56Sopenharmony_ci 2987db96d56Sopenharmony_ci .. versionadded:: 3.1 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci 3017db96d56Sopenharmony_ci.. function:: count(start=0, step=1) 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_ci Make an iterator that returns evenly spaced values starting with number *start*. Often 3047db96d56Sopenharmony_ci used as an argument to :func:`map` to generate consecutive data points. 3057db96d56Sopenharmony_ci Also, used with :func:`zip` to add sequence numbers. Roughly equivalent to:: 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci def count(start=0, step=1): 3087db96d56Sopenharmony_ci # count(10) --> 10 11 12 13 14 ... 3097db96d56Sopenharmony_ci # count(2.5, 0.5) --> 2.5 3.0 3.5 ... 3107db96d56Sopenharmony_ci n = start 3117db96d56Sopenharmony_ci while True: 3127db96d56Sopenharmony_ci yield n 3137db96d56Sopenharmony_ci n += step 3147db96d56Sopenharmony_ci 3157db96d56Sopenharmony_ci When counting with floating point numbers, better accuracy can sometimes be 3167db96d56Sopenharmony_ci achieved by substituting multiplicative code such as: ``(start + step * i 3177db96d56Sopenharmony_ci for i in count())``. 3187db96d56Sopenharmony_ci 3197db96d56Sopenharmony_ci .. versionchanged:: 3.1 3207db96d56Sopenharmony_ci Added *step* argument and allowed non-integer arguments. 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci.. function:: cycle(iterable) 3237db96d56Sopenharmony_ci 3247db96d56Sopenharmony_ci Make an iterator returning elements from the iterable and saving a copy of each. 3257db96d56Sopenharmony_ci When the iterable is exhausted, return elements from the saved copy. Repeats 3267db96d56Sopenharmony_ci indefinitely. Roughly equivalent to:: 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_ci def cycle(iterable): 3297db96d56Sopenharmony_ci # cycle('ABCD') --> A B C D A B C D A B C D ... 3307db96d56Sopenharmony_ci saved = [] 3317db96d56Sopenharmony_ci for element in iterable: 3327db96d56Sopenharmony_ci yield element 3337db96d56Sopenharmony_ci saved.append(element) 3347db96d56Sopenharmony_ci while saved: 3357db96d56Sopenharmony_ci for element in saved: 3367db96d56Sopenharmony_ci yield element 3377db96d56Sopenharmony_ci 3387db96d56Sopenharmony_ci Note, this member of the toolkit may require significant auxiliary storage 3397db96d56Sopenharmony_ci (depending on the length of the iterable). 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci 3427db96d56Sopenharmony_ci.. function:: dropwhile(predicate, iterable) 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ci Make an iterator that drops elements from the iterable as long as the predicate 3457db96d56Sopenharmony_ci is true; afterwards, returns every element. Note, the iterator does not produce 3467db96d56Sopenharmony_ci *any* output until the predicate first becomes false, so it may have a lengthy 3477db96d56Sopenharmony_ci start-up time. Roughly equivalent to:: 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_ci def dropwhile(predicate, iterable): 3507db96d56Sopenharmony_ci # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1 3517db96d56Sopenharmony_ci iterable = iter(iterable) 3527db96d56Sopenharmony_ci for x in iterable: 3537db96d56Sopenharmony_ci if not predicate(x): 3547db96d56Sopenharmony_ci yield x 3557db96d56Sopenharmony_ci break 3567db96d56Sopenharmony_ci for x in iterable: 3577db96d56Sopenharmony_ci yield x 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci.. function:: filterfalse(predicate, iterable) 3607db96d56Sopenharmony_ci 3617db96d56Sopenharmony_ci Make an iterator that filters elements from iterable returning only those for 3627db96d56Sopenharmony_ci which the predicate is false. If *predicate* is ``None``, return the items 3637db96d56Sopenharmony_ci that are false. Roughly equivalent to:: 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci def filterfalse(predicate, iterable): 3667db96d56Sopenharmony_ci # filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8 3677db96d56Sopenharmony_ci if predicate is None: 3687db96d56Sopenharmony_ci predicate = bool 3697db96d56Sopenharmony_ci for x in iterable: 3707db96d56Sopenharmony_ci if not predicate(x): 3717db96d56Sopenharmony_ci yield x 3727db96d56Sopenharmony_ci 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ci.. function:: groupby(iterable, key=None) 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_ci Make an iterator that returns consecutive keys and groups from the *iterable*. 3777db96d56Sopenharmony_ci The *key* is a function computing a key value for each element. If not 3787db96d56Sopenharmony_ci specified or is ``None``, *key* defaults to an identity function and returns 3797db96d56Sopenharmony_ci the element unchanged. Generally, the iterable needs to already be sorted on 3807db96d56Sopenharmony_ci the same key function. 3817db96d56Sopenharmony_ci 3827db96d56Sopenharmony_ci The operation of :func:`groupby` is similar to the ``uniq`` filter in Unix. It 3837db96d56Sopenharmony_ci generates a break or new group every time the value of the key function changes 3847db96d56Sopenharmony_ci (which is why it is usually necessary to have sorted the data using the same key 3857db96d56Sopenharmony_ci function). That behavior differs from SQL's GROUP BY which aggregates common 3867db96d56Sopenharmony_ci elements regardless of their input order. 3877db96d56Sopenharmony_ci 3887db96d56Sopenharmony_ci The returned group is itself an iterator that shares the underlying iterable 3897db96d56Sopenharmony_ci with :func:`groupby`. Because the source is shared, when the :func:`groupby` 3907db96d56Sopenharmony_ci object is advanced, the previous group is no longer visible. So, if that data 3917db96d56Sopenharmony_ci is needed later, it should be stored as a list:: 3927db96d56Sopenharmony_ci 3937db96d56Sopenharmony_ci groups = [] 3947db96d56Sopenharmony_ci uniquekeys = [] 3957db96d56Sopenharmony_ci data = sorted(data, key=keyfunc) 3967db96d56Sopenharmony_ci for k, g in groupby(data, keyfunc): 3977db96d56Sopenharmony_ci groups.append(list(g)) # Store group iterator as a list 3987db96d56Sopenharmony_ci uniquekeys.append(k) 3997db96d56Sopenharmony_ci 4007db96d56Sopenharmony_ci :func:`groupby` is roughly equivalent to:: 4017db96d56Sopenharmony_ci 4027db96d56Sopenharmony_ci class groupby: 4037db96d56Sopenharmony_ci # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B 4047db96d56Sopenharmony_ci # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D 4057db96d56Sopenharmony_ci 4067db96d56Sopenharmony_ci def __init__(self, iterable, key=None): 4077db96d56Sopenharmony_ci if key is None: 4087db96d56Sopenharmony_ci key = lambda x: x 4097db96d56Sopenharmony_ci self.keyfunc = key 4107db96d56Sopenharmony_ci self.it = iter(iterable) 4117db96d56Sopenharmony_ci self.tgtkey = self.currkey = self.currvalue = object() 4127db96d56Sopenharmony_ci 4137db96d56Sopenharmony_ci def __iter__(self): 4147db96d56Sopenharmony_ci return self 4157db96d56Sopenharmony_ci 4167db96d56Sopenharmony_ci def __next__(self): 4177db96d56Sopenharmony_ci self.id = object() 4187db96d56Sopenharmony_ci while self.currkey == self.tgtkey: 4197db96d56Sopenharmony_ci self.currvalue = next(self.it) # Exit on StopIteration 4207db96d56Sopenharmony_ci self.currkey = self.keyfunc(self.currvalue) 4217db96d56Sopenharmony_ci self.tgtkey = self.currkey 4227db96d56Sopenharmony_ci return (self.currkey, self._grouper(self.tgtkey, self.id)) 4237db96d56Sopenharmony_ci 4247db96d56Sopenharmony_ci def _grouper(self, tgtkey, id): 4257db96d56Sopenharmony_ci while self.id is id and self.currkey == tgtkey: 4267db96d56Sopenharmony_ci yield self.currvalue 4277db96d56Sopenharmony_ci try: 4287db96d56Sopenharmony_ci self.currvalue = next(self.it) 4297db96d56Sopenharmony_ci except StopIteration: 4307db96d56Sopenharmony_ci return 4317db96d56Sopenharmony_ci self.currkey = self.keyfunc(self.currvalue) 4327db96d56Sopenharmony_ci 4337db96d56Sopenharmony_ci 4347db96d56Sopenharmony_ci.. function:: islice(iterable, stop) 4357db96d56Sopenharmony_ci islice(iterable, start, stop[, step]) 4367db96d56Sopenharmony_ci 4377db96d56Sopenharmony_ci Make an iterator that returns selected elements from the iterable. If *start* is 4387db96d56Sopenharmony_ci non-zero, then elements from the iterable are skipped until start is reached. 4397db96d56Sopenharmony_ci Afterward, elements are returned consecutively unless *step* is set higher than 4407db96d56Sopenharmony_ci one which results in items being skipped. If *stop* is ``None``, then iteration 4417db96d56Sopenharmony_ci continues until the iterator is exhausted, if at all; otherwise, it stops at the 4427db96d56Sopenharmony_ci specified position. 4437db96d56Sopenharmony_ci 4447db96d56Sopenharmony_ci If *start* is ``None``, then iteration starts at zero. If *step* is ``None``, 4457db96d56Sopenharmony_ci then the step defaults to one. 4467db96d56Sopenharmony_ci 4477db96d56Sopenharmony_ci Unlike regular slicing, :func:`islice` does not support negative values for 4487db96d56Sopenharmony_ci *start*, *stop*, or *step*. Can be used to extract related fields from 4497db96d56Sopenharmony_ci data where the internal structure has been flattened (for example, a 4507db96d56Sopenharmony_ci multi-line report may list a name field on every third line). 4517db96d56Sopenharmony_ci 4527db96d56Sopenharmony_ci Roughly equivalent to:: 4537db96d56Sopenharmony_ci 4547db96d56Sopenharmony_ci def islice(iterable, *args): 4557db96d56Sopenharmony_ci # islice('ABCDEFG', 2) --> A B 4567db96d56Sopenharmony_ci # islice('ABCDEFG', 2, 4) --> C D 4577db96d56Sopenharmony_ci # islice('ABCDEFG', 2, None) --> C D E F G 4587db96d56Sopenharmony_ci # islice('ABCDEFG', 0, None, 2) --> A C E G 4597db96d56Sopenharmony_ci s = slice(*args) 4607db96d56Sopenharmony_ci start, stop, step = s.start or 0, s.stop or sys.maxsize, s.step or 1 4617db96d56Sopenharmony_ci it = iter(range(start, stop, step)) 4627db96d56Sopenharmony_ci try: 4637db96d56Sopenharmony_ci nexti = next(it) 4647db96d56Sopenharmony_ci except StopIteration: 4657db96d56Sopenharmony_ci # Consume *iterable* up to the *start* position. 4667db96d56Sopenharmony_ci for i, element in zip(range(start), iterable): 4677db96d56Sopenharmony_ci pass 4687db96d56Sopenharmony_ci return 4697db96d56Sopenharmony_ci try: 4707db96d56Sopenharmony_ci for i, element in enumerate(iterable): 4717db96d56Sopenharmony_ci if i == nexti: 4727db96d56Sopenharmony_ci yield element 4737db96d56Sopenharmony_ci nexti = next(it) 4747db96d56Sopenharmony_ci except StopIteration: 4757db96d56Sopenharmony_ci # Consume to *stop*. 4767db96d56Sopenharmony_ci for i, element in zip(range(i + 1, stop), iterable): 4777db96d56Sopenharmony_ci pass 4787db96d56Sopenharmony_ci 4797db96d56Sopenharmony_ci 4807db96d56Sopenharmony_ci.. function:: pairwise(iterable) 4817db96d56Sopenharmony_ci 4827db96d56Sopenharmony_ci Return successive overlapping pairs taken from the input *iterable*. 4837db96d56Sopenharmony_ci 4847db96d56Sopenharmony_ci The number of 2-tuples in the output iterator will be one fewer than the 4857db96d56Sopenharmony_ci number of inputs. It will be empty if the input iterable has fewer than 4867db96d56Sopenharmony_ci two values. 4877db96d56Sopenharmony_ci 4887db96d56Sopenharmony_ci Roughly equivalent to:: 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ci def pairwise(iterable): 4917db96d56Sopenharmony_ci # pairwise('ABCDEFG') --> AB BC CD DE EF FG 4927db96d56Sopenharmony_ci a, b = tee(iterable) 4937db96d56Sopenharmony_ci next(b, None) 4947db96d56Sopenharmony_ci return zip(a, b) 4957db96d56Sopenharmony_ci 4967db96d56Sopenharmony_ci .. versionadded:: 3.10 4977db96d56Sopenharmony_ci 4987db96d56Sopenharmony_ci 4997db96d56Sopenharmony_ci.. function:: permutations(iterable, r=None) 5007db96d56Sopenharmony_ci 5017db96d56Sopenharmony_ci Return successive *r* length permutations of elements in the *iterable*. 5027db96d56Sopenharmony_ci 5037db96d56Sopenharmony_ci If *r* is not specified or is ``None``, then *r* defaults to the length 5047db96d56Sopenharmony_ci of the *iterable* and all possible full-length permutations 5057db96d56Sopenharmony_ci are generated. 5067db96d56Sopenharmony_ci 5077db96d56Sopenharmony_ci The permutation tuples are emitted in lexicographic order according to 5087db96d56Sopenharmony_ci the order of the input *iterable*. So, if the input *iterable* is sorted, 5097db96d56Sopenharmony_ci the output tuples will be produced in sorted order. 5107db96d56Sopenharmony_ci 5117db96d56Sopenharmony_ci Elements are treated as unique based on their position, not on their 5127db96d56Sopenharmony_ci value. So if the input elements are unique, there will be no repeated 5137db96d56Sopenharmony_ci values within a permutation. 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci Roughly equivalent to:: 5167db96d56Sopenharmony_ci 5177db96d56Sopenharmony_ci def permutations(iterable, r=None): 5187db96d56Sopenharmony_ci # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC 5197db96d56Sopenharmony_ci # permutations(range(3)) --> 012 021 102 120 201 210 5207db96d56Sopenharmony_ci pool = tuple(iterable) 5217db96d56Sopenharmony_ci n = len(pool) 5227db96d56Sopenharmony_ci r = n if r is None else r 5237db96d56Sopenharmony_ci if r > n: 5247db96d56Sopenharmony_ci return 5257db96d56Sopenharmony_ci indices = list(range(n)) 5267db96d56Sopenharmony_ci cycles = list(range(n, n-r, -1)) 5277db96d56Sopenharmony_ci yield tuple(pool[i] for i in indices[:r]) 5287db96d56Sopenharmony_ci while n: 5297db96d56Sopenharmony_ci for i in reversed(range(r)): 5307db96d56Sopenharmony_ci cycles[i] -= 1 5317db96d56Sopenharmony_ci if cycles[i] == 0: 5327db96d56Sopenharmony_ci indices[i:] = indices[i+1:] + indices[i:i+1] 5337db96d56Sopenharmony_ci cycles[i] = n - i 5347db96d56Sopenharmony_ci else: 5357db96d56Sopenharmony_ci j = cycles[i] 5367db96d56Sopenharmony_ci indices[i], indices[-j] = indices[-j], indices[i] 5377db96d56Sopenharmony_ci yield tuple(pool[i] for i in indices[:r]) 5387db96d56Sopenharmony_ci break 5397db96d56Sopenharmony_ci else: 5407db96d56Sopenharmony_ci return 5417db96d56Sopenharmony_ci 5427db96d56Sopenharmony_ci The code for :func:`permutations` can be also expressed as a subsequence of 5437db96d56Sopenharmony_ci :func:`product`, filtered to exclude entries with repeated elements (those 5447db96d56Sopenharmony_ci from the same position in the input pool):: 5457db96d56Sopenharmony_ci 5467db96d56Sopenharmony_ci def permutations(iterable, r=None): 5477db96d56Sopenharmony_ci pool = tuple(iterable) 5487db96d56Sopenharmony_ci n = len(pool) 5497db96d56Sopenharmony_ci r = n if r is None else r 5507db96d56Sopenharmony_ci for indices in product(range(n), repeat=r): 5517db96d56Sopenharmony_ci if len(set(indices)) == r: 5527db96d56Sopenharmony_ci yield tuple(pool[i] for i in indices) 5537db96d56Sopenharmony_ci 5547db96d56Sopenharmony_ci The number of items returned is ``n! / (n-r)!`` when ``0 <= r <= n`` 5557db96d56Sopenharmony_ci or zero when ``r > n``. 5567db96d56Sopenharmony_ci 5577db96d56Sopenharmony_ci.. function:: product(*iterables, repeat=1) 5587db96d56Sopenharmony_ci 5597db96d56Sopenharmony_ci Cartesian product of input iterables. 5607db96d56Sopenharmony_ci 5617db96d56Sopenharmony_ci Roughly equivalent to nested for-loops in a generator expression. For example, 5627db96d56Sopenharmony_ci ``product(A, B)`` returns the same as ``((x,y) for x in A for y in B)``. 5637db96d56Sopenharmony_ci 5647db96d56Sopenharmony_ci The nested loops cycle like an odometer with the rightmost element advancing 5657db96d56Sopenharmony_ci on every iteration. This pattern creates a lexicographic ordering so that if 5667db96d56Sopenharmony_ci the input's iterables are sorted, the product tuples are emitted in sorted 5677db96d56Sopenharmony_ci order. 5687db96d56Sopenharmony_ci 5697db96d56Sopenharmony_ci To compute the product of an iterable with itself, specify the number of 5707db96d56Sopenharmony_ci repetitions with the optional *repeat* keyword argument. For example, 5717db96d56Sopenharmony_ci ``product(A, repeat=4)`` means the same as ``product(A, A, A, A)``. 5727db96d56Sopenharmony_ci 5737db96d56Sopenharmony_ci This function is roughly equivalent to the following code, except that the 5747db96d56Sopenharmony_ci actual implementation does not build up intermediate results in memory:: 5757db96d56Sopenharmony_ci 5767db96d56Sopenharmony_ci def product(*args, repeat=1): 5777db96d56Sopenharmony_ci # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy 5787db96d56Sopenharmony_ci # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 5797db96d56Sopenharmony_ci pools = [tuple(pool) for pool in args] * repeat 5807db96d56Sopenharmony_ci result = [[]] 5817db96d56Sopenharmony_ci for pool in pools: 5827db96d56Sopenharmony_ci result = [x+[y] for x in result for y in pool] 5837db96d56Sopenharmony_ci for prod in result: 5847db96d56Sopenharmony_ci yield tuple(prod) 5857db96d56Sopenharmony_ci 5867db96d56Sopenharmony_ci Before :func:`product` runs, it completely consumes the input iterables, 5877db96d56Sopenharmony_ci keeping pools of values in memory to generate the products. Accordingly, 5887db96d56Sopenharmony_ci it is only useful with finite inputs. 5897db96d56Sopenharmony_ci 5907db96d56Sopenharmony_ci.. function:: repeat(object[, times]) 5917db96d56Sopenharmony_ci 5927db96d56Sopenharmony_ci Make an iterator that returns *object* over and over again. Runs indefinitely 5937db96d56Sopenharmony_ci unless the *times* argument is specified. 5947db96d56Sopenharmony_ci 5957db96d56Sopenharmony_ci Roughly equivalent to:: 5967db96d56Sopenharmony_ci 5977db96d56Sopenharmony_ci def repeat(object, times=None): 5987db96d56Sopenharmony_ci # repeat(10, 3) --> 10 10 10 5997db96d56Sopenharmony_ci if times is None: 6007db96d56Sopenharmony_ci while True: 6017db96d56Sopenharmony_ci yield object 6027db96d56Sopenharmony_ci else: 6037db96d56Sopenharmony_ci for i in range(times): 6047db96d56Sopenharmony_ci yield object 6057db96d56Sopenharmony_ci 6067db96d56Sopenharmony_ci A common use for *repeat* is to supply a stream of constant values to *map* 6077db96d56Sopenharmony_ci or *zip*: 6087db96d56Sopenharmony_ci 6097db96d56Sopenharmony_ci .. doctest:: 6107db96d56Sopenharmony_ci 6117db96d56Sopenharmony_ci >>> list(map(pow, range(10), repeat(2))) 6127db96d56Sopenharmony_ci [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 6137db96d56Sopenharmony_ci 6147db96d56Sopenharmony_ci.. function:: starmap(function, iterable) 6157db96d56Sopenharmony_ci 6167db96d56Sopenharmony_ci Make an iterator that computes the function using arguments obtained from 6177db96d56Sopenharmony_ci the iterable. Used instead of :func:`map` when argument parameters are already 6187db96d56Sopenharmony_ci grouped in tuples from a single iterable (when the data has been 6197db96d56Sopenharmony_ci "pre-zipped"). 6207db96d56Sopenharmony_ci 6217db96d56Sopenharmony_ci The difference between :func:`map` and :func:`starmap` parallels the 6227db96d56Sopenharmony_ci distinction between ``function(a,b)`` and ``function(*c)``. Roughly 6237db96d56Sopenharmony_ci equivalent to:: 6247db96d56Sopenharmony_ci 6257db96d56Sopenharmony_ci def starmap(function, iterable): 6267db96d56Sopenharmony_ci # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000 6277db96d56Sopenharmony_ci for args in iterable: 6287db96d56Sopenharmony_ci yield function(*args) 6297db96d56Sopenharmony_ci 6307db96d56Sopenharmony_ci 6317db96d56Sopenharmony_ci.. function:: takewhile(predicate, iterable) 6327db96d56Sopenharmony_ci 6337db96d56Sopenharmony_ci Make an iterator that returns elements from the iterable as long as the 6347db96d56Sopenharmony_ci predicate is true. Roughly equivalent to:: 6357db96d56Sopenharmony_ci 6367db96d56Sopenharmony_ci def takewhile(predicate, iterable): 6377db96d56Sopenharmony_ci # takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4 6387db96d56Sopenharmony_ci for x in iterable: 6397db96d56Sopenharmony_ci if predicate(x): 6407db96d56Sopenharmony_ci yield x 6417db96d56Sopenharmony_ci else: 6427db96d56Sopenharmony_ci break 6437db96d56Sopenharmony_ci 6447db96d56Sopenharmony_ci 6457db96d56Sopenharmony_ci.. function:: tee(iterable, n=2) 6467db96d56Sopenharmony_ci 6477db96d56Sopenharmony_ci Return *n* independent iterators from a single iterable. 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_ci The following Python code helps explain what *tee* does (although the actual 6507db96d56Sopenharmony_ci implementation is more complex and uses only a single underlying 6517db96d56Sopenharmony_ci :abbr:`FIFO (first-in, first-out)` queue):: 6527db96d56Sopenharmony_ci 6537db96d56Sopenharmony_ci def tee(iterable, n=2): 6547db96d56Sopenharmony_ci it = iter(iterable) 6557db96d56Sopenharmony_ci deques = [collections.deque() for i in range(n)] 6567db96d56Sopenharmony_ci def gen(mydeque): 6577db96d56Sopenharmony_ci while True: 6587db96d56Sopenharmony_ci if not mydeque: # when the local deque is empty 6597db96d56Sopenharmony_ci try: 6607db96d56Sopenharmony_ci newval = next(it) # fetch a new value and 6617db96d56Sopenharmony_ci except StopIteration: 6627db96d56Sopenharmony_ci return 6637db96d56Sopenharmony_ci for d in deques: # load it to all the deques 6647db96d56Sopenharmony_ci d.append(newval) 6657db96d56Sopenharmony_ci yield mydeque.popleft() 6667db96d56Sopenharmony_ci return tuple(gen(d) for d in deques) 6677db96d56Sopenharmony_ci 6687db96d56Sopenharmony_ci Once a :func:`tee` has been created, the original *iterable* should not be 6697db96d56Sopenharmony_ci used anywhere else; otherwise, the *iterable* could get advanced without 6707db96d56Sopenharmony_ci the tee objects being informed. 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci ``tee`` iterators are not threadsafe. A :exc:`RuntimeError` may be 6737db96d56Sopenharmony_ci raised when using simultaneously iterators returned by the same :func:`tee` 6747db96d56Sopenharmony_ci call, even if the original *iterable* is threadsafe. 6757db96d56Sopenharmony_ci 6767db96d56Sopenharmony_ci This itertool may require significant auxiliary storage (depending on how 6777db96d56Sopenharmony_ci much temporary data needs to be stored). In general, if one iterator uses 6787db96d56Sopenharmony_ci most or all of the data before another iterator starts, it is faster to use 6797db96d56Sopenharmony_ci :func:`list` instead of :func:`tee`. 6807db96d56Sopenharmony_ci 6817db96d56Sopenharmony_ci 6827db96d56Sopenharmony_ci.. function:: zip_longest(*iterables, fillvalue=None) 6837db96d56Sopenharmony_ci 6847db96d56Sopenharmony_ci Make an iterator that aggregates elements from each of the iterables. If the 6857db96d56Sopenharmony_ci iterables are of uneven length, missing values are filled-in with *fillvalue*. 6867db96d56Sopenharmony_ci Iteration continues until the longest iterable is exhausted. Roughly equivalent to:: 6877db96d56Sopenharmony_ci 6887db96d56Sopenharmony_ci def zip_longest(*args, fillvalue=None): 6897db96d56Sopenharmony_ci # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D- 6907db96d56Sopenharmony_ci iterators = [iter(it) for it in args] 6917db96d56Sopenharmony_ci num_active = len(iterators) 6927db96d56Sopenharmony_ci if not num_active: 6937db96d56Sopenharmony_ci return 6947db96d56Sopenharmony_ci while True: 6957db96d56Sopenharmony_ci values = [] 6967db96d56Sopenharmony_ci for i, it in enumerate(iterators): 6977db96d56Sopenharmony_ci try: 6987db96d56Sopenharmony_ci value = next(it) 6997db96d56Sopenharmony_ci except StopIteration: 7007db96d56Sopenharmony_ci num_active -= 1 7017db96d56Sopenharmony_ci if not num_active: 7027db96d56Sopenharmony_ci return 7037db96d56Sopenharmony_ci iterators[i] = repeat(fillvalue) 7047db96d56Sopenharmony_ci value = fillvalue 7057db96d56Sopenharmony_ci values.append(value) 7067db96d56Sopenharmony_ci yield tuple(values) 7077db96d56Sopenharmony_ci 7087db96d56Sopenharmony_ci If one of the iterables is potentially infinite, then the :func:`zip_longest` 7097db96d56Sopenharmony_ci function should be wrapped with something that limits the number of calls 7107db96d56Sopenharmony_ci (for example :func:`islice` or :func:`takewhile`). If not specified, 7117db96d56Sopenharmony_ci *fillvalue* defaults to ``None``. 7127db96d56Sopenharmony_ci 7137db96d56Sopenharmony_ci 7147db96d56Sopenharmony_ci.. _itertools-recipes: 7157db96d56Sopenharmony_ci 7167db96d56Sopenharmony_ciItertools Recipes 7177db96d56Sopenharmony_ci----------------- 7187db96d56Sopenharmony_ci 7197db96d56Sopenharmony_ciThis section shows recipes for creating an extended toolset using the existing 7207db96d56Sopenharmony_ciitertools as building blocks. 7217db96d56Sopenharmony_ci 7227db96d56Sopenharmony_ciThe primary purpose of the itertools recipes is educational. The recipes show 7237db96d56Sopenharmony_civarious ways of thinking about individual tools — for example, that 7247db96d56Sopenharmony_ci``chain.from_iterable`` is related to the concept of flattening. The recipes 7257db96d56Sopenharmony_cialso give ideas about ways that the tools can be combined — for example, how 7267db96d56Sopenharmony_ci``compress()`` and ``range()`` can work together. The recipes also show patterns 7277db96d56Sopenharmony_cifor using itertools with the :mod:`operator` and :mod:`collections` modules as 7287db96d56Sopenharmony_ciwell as with the built-in itertools such as ``map()``, ``filter()``, 7297db96d56Sopenharmony_ci``reversed()``, and ``enumerate()``. 7307db96d56Sopenharmony_ci 7317db96d56Sopenharmony_ciA secondary purpose of the recipes is to serve as an incubator. The 7327db96d56Sopenharmony_ci``accumulate()``, ``compress()``, and ``pairwise()`` itertools started out as 7337db96d56Sopenharmony_cirecipes. Currently, the ``iter_index()`` recipe is being tested to see 7347db96d56Sopenharmony_ciwhether it proves its worth. 7357db96d56Sopenharmony_ci 7367db96d56Sopenharmony_ciSubstantially all of these recipes and many, many others can be installed from 7377db96d56Sopenharmony_cithe `more-itertools project <https://pypi.org/project/more-itertools/>`_ found 7387db96d56Sopenharmony_cion the Python Package Index:: 7397db96d56Sopenharmony_ci 7407db96d56Sopenharmony_ci python -m pip install more-itertools 7417db96d56Sopenharmony_ci 7427db96d56Sopenharmony_ciMany of the recipes offer the same high performance as the underlying toolset. 7437db96d56Sopenharmony_ciSuperior memory performance is kept by processing elements one at a time 7447db96d56Sopenharmony_cirather than bringing the whole iterable into memory all at once. Code volume is 7457db96d56Sopenharmony_cikept small by linking the tools together in a functional style which helps 7467db96d56Sopenharmony_cieliminate temporary variables. High speed is retained by preferring 7477db96d56Sopenharmony_ci"vectorized" building blocks over the use of for-loops and :term:`generator`\s 7487db96d56Sopenharmony_ciwhich incur interpreter overhead. 7497db96d56Sopenharmony_ci 7507db96d56Sopenharmony_ci.. testcode:: 7517db96d56Sopenharmony_ci 7527db96d56Sopenharmony_ci import collections 7537db96d56Sopenharmony_ci import math 7547db96d56Sopenharmony_ci import operator 7557db96d56Sopenharmony_ci import random 7567db96d56Sopenharmony_ci 7577db96d56Sopenharmony_ci def take(n, iterable): 7587db96d56Sopenharmony_ci "Return first n items of the iterable as a list" 7597db96d56Sopenharmony_ci return list(islice(iterable, n)) 7607db96d56Sopenharmony_ci 7617db96d56Sopenharmony_ci def prepend(value, iterator): 7627db96d56Sopenharmony_ci "Prepend a single value in front of an iterator" 7637db96d56Sopenharmony_ci # prepend(1, [2, 3, 4]) --> 1 2 3 4 7647db96d56Sopenharmony_ci return chain([value], iterator) 7657db96d56Sopenharmony_ci 7667db96d56Sopenharmony_ci def tabulate(function, start=0): 7677db96d56Sopenharmony_ci "Return function(0), function(1), ..." 7687db96d56Sopenharmony_ci return map(function, count(start)) 7697db96d56Sopenharmony_ci 7707db96d56Sopenharmony_ci def tail(n, iterable): 7717db96d56Sopenharmony_ci "Return an iterator over the last n items" 7727db96d56Sopenharmony_ci # tail(3, 'ABCDEFG') --> E F G 7737db96d56Sopenharmony_ci return iter(collections.deque(iterable, maxlen=n)) 7747db96d56Sopenharmony_ci 7757db96d56Sopenharmony_ci def consume(iterator, n=None): 7767db96d56Sopenharmony_ci "Advance the iterator n-steps ahead. If n is None, consume entirely." 7777db96d56Sopenharmony_ci # Use functions that consume iterators at C speed. 7787db96d56Sopenharmony_ci if n is None: 7797db96d56Sopenharmony_ci # feed the entire iterator into a zero-length deque 7807db96d56Sopenharmony_ci collections.deque(iterator, maxlen=0) 7817db96d56Sopenharmony_ci else: 7827db96d56Sopenharmony_ci # advance to the empty slice starting at position n 7837db96d56Sopenharmony_ci next(islice(iterator, n, n), None) 7847db96d56Sopenharmony_ci 7857db96d56Sopenharmony_ci def nth(iterable, n, default=None): 7867db96d56Sopenharmony_ci "Returns the nth item or a default value" 7877db96d56Sopenharmony_ci return next(islice(iterable, n, None), default) 7887db96d56Sopenharmony_ci 7897db96d56Sopenharmony_ci def all_equal(iterable): 7907db96d56Sopenharmony_ci "Returns True if all the elements are equal to each other" 7917db96d56Sopenharmony_ci g = groupby(iterable) 7927db96d56Sopenharmony_ci return next(g, True) and not next(g, False) 7937db96d56Sopenharmony_ci 7947db96d56Sopenharmony_ci def quantify(iterable, pred=bool): 7957db96d56Sopenharmony_ci "Count how many times the predicate is True" 7967db96d56Sopenharmony_ci return sum(map(pred, iterable)) 7977db96d56Sopenharmony_ci 7987db96d56Sopenharmony_ci def ncycles(iterable, n): 7997db96d56Sopenharmony_ci "Returns the sequence elements n times" 8007db96d56Sopenharmony_ci return chain.from_iterable(repeat(tuple(iterable), n)) 8017db96d56Sopenharmony_ci 8027db96d56Sopenharmony_ci def batched(iterable, n): 8037db96d56Sopenharmony_ci "Batch data into tuples of length n. The last batch may be shorter." 8047db96d56Sopenharmony_ci # batched('ABCDEFG', 3) --> ABC DEF G 8057db96d56Sopenharmony_ci if n < 1: 8067db96d56Sopenharmony_ci raise ValueError('n must be at least one') 8077db96d56Sopenharmony_ci it = iter(iterable) 8087db96d56Sopenharmony_ci while batch := tuple(islice(it, n)): 8097db96d56Sopenharmony_ci yield batch 8107db96d56Sopenharmony_ci 8117db96d56Sopenharmony_ci def grouper(iterable, n, *, incomplete='fill', fillvalue=None): 8127db96d56Sopenharmony_ci "Collect data into non-overlapping fixed-length chunks or blocks" 8137db96d56Sopenharmony_ci # grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx 8147db96d56Sopenharmony_ci # grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError 8157db96d56Sopenharmony_ci # grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF 8167db96d56Sopenharmony_ci args = [iter(iterable)] * n 8177db96d56Sopenharmony_ci if incomplete == 'fill': 8187db96d56Sopenharmony_ci return zip_longest(*args, fillvalue=fillvalue) 8197db96d56Sopenharmony_ci if incomplete == 'strict': 8207db96d56Sopenharmony_ci return zip(*args, strict=True) 8217db96d56Sopenharmony_ci if incomplete == 'ignore': 8227db96d56Sopenharmony_ci return zip(*args) 8237db96d56Sopenharmony_ci else: 8247db96d56Sopenharmony_ci raise ValueError('Expected fill, strict, or ignore') 8257db96d56Sopenharmony_ci 8267db96d56Sopenharmony_ci def sumprod(vec1, vec2): 8277db96d56Sopenharmony_ci "Compute a sum of products." 8287db96d56Sopenharmony_ci return sum(starmap(operator.mul, zip(vec1, vec2, strict=True))) 8297db96d56Sopenharmony_ci 8307db96d56Sopenharmony_ci def sum_of_squares(it): 8317db96d56Sopenharmony_ci "Add up the squares of the input values." 8327db96d56Sopenharmony_ci # sum_of_squares([10, 20, 30]) -> 1400 8337db96d56Sopenharmony_ci return sumprod(*tee(it)) 8347db96d56Sopenharmony_ci 8357db96d56Sopenharmony_ci def transpose(it): 8367db96d56Sopenharmony_ci "Swap the rows and columns of the input." 8377db96d56Sopenharmony_ci # transpose([(1, 2, 3), (11, 22, 33)]) --> (1, 11) (2, 22) (3, 33) 8387db96d56Sopenharmony_ci return zip(*it, strict=True) 8397db96d56Sopenharmony_ci 8407db96d56Sopenharmony_ci def matmul(m1, m2): 8417db96d56Sopenharmony_ci "Multiply two matrices." 8427db96d56Sopenharmony_ci # matmul([(7, 5), (3, 5)], [[2, 5], [7, 9]]) --> (49, 80), (41, 60) 8437db96d56Sopenharmony_ci n = len(m2[0]) 8447db96d56Sopenharmony_ci return batched(starmap(sumprod, product(m1, transpose(m2))), n) 8457db96d56Sopenharmony_ci 8467db96d56Sopenharmony_ci def convolve(signal, kernel): 8477db96d56Sopenharmony_ci # See: https://betterexplained.com/articles/intuitive-convolution/ 8487db96d56Sopenharmony_ci # convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur) 8497db96d56Sopenharmony_ci # convolve(data, [1, -1]) --> 1st finite difference (1st derivative) 8507db96d56Sopenharmony_ci # convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative) 8517db96d56Sopenharmony_ci kernel = tuple(kernel)[::-1] 8527db96d56Sopenharmony_ci n = len(kernel) 8537db96d56Sopenharmony_ci window = collections.deque([0], maxlen=n) * n 8547db96d56Sopenharmony_ci for x in chain(signal, repeat(0, n-1)): 8557db96d56Sopenharmony_ci window.append(x) 8567db96d56Sopenharmony_ci yield sumprod(kernel, window) 8577db96d56Sopenharmony_ci 8587db96d56Sopenharmony_ci def polynomial_from_roots(roots): 8597db96d56Sopenharmony_ci """Compute a polynomial's coefficients from its roots. 8607db96d56Sopenharmony_ci 8617db96d56Sopenharmony_ci (x - 5) (x + 4) (x - 3) expands to: x³ -4x² -17x + 60 8627db96d56Sopenharmony_ci """ 8637db96d56Sopenharmony_ci # polynomial_from_roots([5, -4, 3]) --> [1, -4, -17, 60] 8647db96d56Sopenharmony_ci expansion = [1] 8657db96d56Sopenharmony_ci for r in roots: 8667db96d56Sopenharmony_ci expansion = convolve(expansion, (1, -r)) 8677db96d56Sopenharmony_ci return list(expansion) 8687db96d56Sopenharmony_ci 8697db96d56Sopenharmony_ci def polynomial_eval(coefficients, x): 8707db96d56Sopenharmony_ci """Evaluate a polynomial at a specific value. 8717db96d56Sopenharmony_ci 8727db96d56Sopenharmony_ci Computes with better numeric stability than Horner's method. 8737db96d56Sopenharmony_ci """ 8747db96d56Sopenharmony_ci # Evaluate x³ -4x² -17x + 60 at x = 2.5 8757db96d56Sopenharmony_ci # polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125 8767db96d56Sopenharmony_ci n = len(coefficients) 8777db96d56Sopenharmony_ci if n == 0: 8787db96d56Sopenharmony_ci return x * 0 # coerce zero to the type of x 8797db96d56Sopenharmony_ci powers = map(pow, repeat(x), reversed(range(n))) 8807db96d56Sopenharmony_ci return sumprod(coefficients, powers) 8817db96d56Sopenharmony_ci 8827db96d56Sopenharmony_ci def iter_index(iterable, value, start=0): 8837db96d56Sopenharmony_ci "Return indices where a value occurs in a sequence or iterable." 8847db96d56Sopenharmony_ci # iter_index('AABCADEAF', 'A') --> 0 1 4 7 8857db96d56Sopenharmony_ci try: 8867db96d56Sopenharmony_ci seq_index = iterable.index 8877db96d56Sopenharmony_ci except AttributeError: 8887db96d56Sopenharmony_ci # Slow path for general iterables 8897db96d56Sopenharmony_ci it = islice(iterable, start, None) 8907db96d56Sopenharmony_ci i = start - 1 8917db96d56Sopenharmony_ci try: 8927db96d56Sopenharmony_ci while True: 8937db96d56Sopenharmony_ci yield (i := i + operator.indexOf(it, value) + 1) 8947db96d56Sopenharmony_ci except ValueError: 8957db96d56Sopenharmony_ci pass 8967db96d56Sopenharmony_ci else: 8977db96d56Sopenharmony_ci # Fast path for sequences 8987db96d56Sopenharmony_ci i = start - 1 8997db96d56Sopenharmony_ci try: 9007db96d56Sopenharmony_ci while True: 9017db96d56Sopenharmony_ci yield (i := seq_index(value, i+1)) 9027db96d56Sopenharmony_ci except ValueError: 9037db96d56Sopenharmony_ci pass 9047db96d56Sopenharmony_ci 9057db96d56Sopenharmony_ci def sieve(n): 9067db96d56Sopenharmony_ci "Primes less than n" 9077db96d56Sopenharmony_ci # sieve(30) --> 2 3 5 7 11 13 17 19 23 29 9087db96d56Sopenharmony_ci data = bytearray((0, 1)) * (n // 2) 9097db96d56Sopenharmony_ci data[:3] = 0, 0, 0 9107db96d56Sopenharmony_ci limit = math.isqrt(n) + 1 9117db96d56Sopenharmony_ci for p in compress(range(limit), data): 9127db96d56Sopenharmony_ci data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p))) 9137db96d56Sopenharmony_ci data[2] = 1 9147db96d56Sopenharmony_ci return iter_index(data, 1) if n > 2 else iter([]) 9157db96d56Sopenharmony_ci 9167db96d56Sopenharmony_ci def factor(n): 9177db96d56Sopenharmony_ci "Prime factors of n." 9187db96d56Sopenharmony_ci # factor(99) --> 3 3 11 9197db96d56Sopenharmony_ci for prime in sieve(math.isqrt(n) + 1): 9207db96d56Sopenharmony_ci while True: 9217db96d56Sopenharmony_ci quotient, remainder = divmod(n, prime) 9227db96d56Sopenharmony_ci if remainder: 9237db96d56Sopenharmony_ci break 9247db96d56Sopenharmony_ci yield prime 9257db96d56Sopenharmony_ci n = quotient 9267db96d56Sopenharmony_ci if n == 1: 9277db96d56Sopenharmony_ci return 9287db96d56Sopenharmony_ci if n > 1: 9297db96d56Sopenharmony_ci yield n 9307db96d56Sopenharmony_ci 9317db96d56Sopenharmony_ci def flatten(list_of_lists): 9327db96d56Sopenharmony_ci "Flatten one level of nesting" 9337db96d56Sopenharmony_ci return chain.from_iterable(list_of_lists) 9347db96d56Sopenharmony_ci 9357db96d56Sopenharmony_ci def repeatfunc(func, times=None, *args): 9367db96d56Sopenharmony_ci """Repeat calls to func with specified arguments. 9377db96d56Sopenharmony_ci 9387db96d56Sopenharmony_ci Example: repeatfunc(random.random) 9397db96d56Sopenharmony_ci """ 9407db96d56Sopenharmony_ci if times is None: 9417db96d56Sopenharmony_ci return starmap(func, repeat(args)) 9427db96d56Sopenharmony_ci return starmap(func, repeat(args, times)) 9437db96d56Sopenharmony_ci 9447db96d56Sopenharmony_ci def triplewise(iterable): 9457db96d56Sopenharmony_ci "Return overlapping triplets from an iterable" 9467db96d56Sopenharmony_ci # triplewise('ABCDEFG') --> ABC BCD CDE DEF EFG 9477db96d56Sopenharmony_ci for (a, _), (b, c) in pairwise(pairwise(iterable)): 9487db96d56Sopenharmony_ci yield a, b, c 9497db96d56Sopenharmony_ci 9507db96d56Sopenharmony_ci def sliding_window(iterable, n): 9517db96d56Sopenharmony_ci # sliding_window('ABCDEFG', 4) --> ABCD BCDE CDEF DEFG 9527db96d56Sopenharmony_ci it = iter(iterable) 9537db96d56Sopenharmony_ci window = collections.deque(islice(it, n), maxlen=n) 9547db96d56Sopenharmony_ci if len(window) == n: 9557db96d56Sopenharmony_ci yield tuple(window) 9567db96d56Sopenharmony_ci for x in it: 9577db96d56Sopenharmony_ci window.append(x) 9587db96d56Sopenharmony_ci yield tuple(window) 9597db96d56Sopenharmony_ci 9607db96d56Sopenharmony_ci def roundrobin(*iterables): 9617db96d56Sopenharmony_ci "roundrobin('ABC', 'D', 'EF') --> A D E B F C" 9627db96d56Sopenharmony_ci # Recipe credited to George Sakkis 9637db96d56Sopenharmony_ci num_active = len(iterables) 9647db96d56Sopenharmony_ci nexts = cycle(iter(it).__next__ for it in iterables) 9657db96d56Sopenharmony_ci while num_active: 9667db96d56Sopenharmony_ci try: 9677db96d56Sopenharmony_ci for next in nexts: 9687db96d56Sopenharmony_ci yield next() 9697db96d56Sopenharmony_ci except StopIteration: 9707db96d56Sopenharmony_ci # Remove the iterator we just exhausted from the cycle. 9717db96d56Sopenharmony_ci num_active -= 1 9727db96d56Sopenharmony_ci nexts = cycle(islice(nexts, num_active)) 9737db96d56Sopenharmony_ci 9747db96d56Sopenharmony_ci def partition(pred, iterable): 9757db96d56Sopenharmony_ci "Use a predicate to partition entries into false entries and true entries" 9767db96d56Sopenharmony_ci # partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9 9777db96d56Sopenharmony_ci t1, t2 = tee(iterable) 9787db96d56Sopenharmony_ci return filterfalse(pred, t1), filter(pred, t2) 9797db96d56Sopenharmony_ci 9807db96d56Sopenharmony_ci def before_and_after(predicate, it): 9817db96d56Sopenharmony_ci """ Variant of takewhile() that allows complete 9827db96d56Sopenharmony_ci access to the remainder of the iterator. 9837db96d56Sopenharmony_ci 9847db96d56Sopenharmony_ci >>> it = iter('ABCdEfGhI') 9857db96d56Sopenharmony_ci >>> all_upper, remainder = before_and_after(str.isupper, it) 9867db96d56Sopenharmony_ci >>> ''.join(all_upper) 9877db96d56Sopenharmony_ci 'ABC' 9887db96d56Sopenharmony_ci >>> ''.join(remainder) # takewhile() would lose the 'd' 9897db96d56Sopenharmony_ci 'dEfGhI' 9907db96d56Sopenharmony_ci 9917db96d56Sopenharmony_ci Note that the first iterator must be fully 9927db96d56Sopenharmony_ci consumed before the second iterator can 9937db96d56Sopenharmony_ci generate valid results. 9947db96d56Sopenharmony_ci """ 9957db96d56Sopenharmony_ci it = iter(it) 9967db96d56Sopenharmony_ci transition = [] 9977db96d56Sopenharmony_ci def true_iterator(): 9987db96d56Sopenharmony_ci for elem in it: 9997db96d56Sopenharmony_ci if predicate(elem): 10007db96d56Sopenharmony_ci yield elem 10017db96d56Sopenharmony_ci else: 10027db96d56Sopenharmony_ci transition.append(elem) 10037db96d56Sopenharmony_ci return 10047db96d56Sopenharmony_ci def remainder_iterator(): 10057db96d56Sopenharmony_ci yield from transition 10067db96d56Sopenharmony_ci yield from it 10077db96d56Sopenharmony_ci return true_iterator(), remainder_iterator() 10087db96d56Sopenharmony_ci 10097db96d56Sopenharmony_ci def subslices(seq): 10107db96d56Sopenharmony_ci "Return all contiguous non-empty subslices of a sequence" 10117db96d56Sopenharmony_ci # subslices('ABCD') --> A AB ABC ABCD B BC BCD C CD D 10127db96d56Sopenharmony_ci slices = starmap(slice, combinations(range(len(seq) + 1), 2)) 10137db96d56Sopenharmony_ci return map(operator.getitem, repeat(seq), slices) 10147db96d56Sopenharmony_ci 10157db96d56Sopenharmony_ci def powerset(iterable): 10167db96d56Sopenharmony_ci "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)" 10177db96d56Sopenharmony_ci s = list(iterable) 10187db96d56Sopenharmony_ci return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) 10197db96d56Sopenharmony_ci 10207db96d56Sopenharmony_ci def unique_everseen(iterable, key=None): 10217db96d56Sopenharmony_ci "List unique elements, preserving order. Remember all elements ever seen." 10227db96d56Sopenharmony_ci # unique_everseen('AAAABBBCCDAABBB') --> A B C D 10237db96d56Sopenharmony_ci # unique_everseen('ABBcCAD', str.lower) --> A B c D 10247db96d56Sopenharmony_ci seen = set() 10257db96d56Sopenharmony_ci if key is None: 10267db96d56Sopenharmony_ci for element in filterfalse(seen.__contains__, iterable): 10277db96d56Sopenharmony_ci seen.add(element) 10287db96d56Sopenharmony_ci yield element 10297db96d56Sopenharmony_ci # For order preserving deduplication, 10307db96d56Sopenharmony_ci # a faster but non-lazy solution is: 10317db96d56Sopenharmony_ci # yield from dict.fromkeys(iterable) 10327db96d56Sopenharmony_ci else: 10337db96d56Sopenharmony_ci for element in iterable: 10347db96d56Sopenharmony_ci k = key(element) 10357db96d56Sopenharmony_ci if k not in seen: 10367db96d56Sopenharmony_ci seen.add(k) 10377db96d56Sopenharmony_ci yield element 10387db96d56Sopenharmony_ci # For use cases that allow the last matching element to be returned, 10397db96d56Sopenharmony_ci # a faster but non-lazy solution is: 10407db96d56Sopenharmony_ci # t1, t2 = tee(iterable) 10417db96d56Sopenharmony_ci # yield from dict(zip(map(key, t1), t2)).values() 10427db96d56Sopenharmony_ci 10437db96d56Sopenharmony_ci def unique_justseen(iterable, key=None): 10447db96d56Sopenharmony_ci "List unique elements, preserving order. Remember only the element just seen." 10457db96d56Sopenharmony_ci # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B 10467db96d56Sopenharmony_ci # unique_justseen('ABBcCAD', str.lower) --> A B c A D 10477db96d56Sopenharmony_ci return map(next, map(operator.itemgetter(1), groupby(iterable, key))) 10487db96d56Sopenharmony_ci 10497db96d56Sopenharmony_ci def iter_except(func, exception, first=None): 10507db96d56Sopenharmony_ci """ Call a function repeatedly until an exception is raised. 10517db96d56Sopenharmony_ci 10527db96d56Sopenharmony_ci Converts a call-until-exception interface to an iterator interface. 10537db96d56Sopenharmony_ci Like builtins.iter(func, sentinel) but uses an exception instead 10547db96d56Sopenharmony_ci of a sentinel to end the loop. 10557db96d56Sopenharmony_ci 10567db96d56Sopenharmony_ci Examples: 10577db96d56Sopenharmony_ci iter_except(functools.partial(heappop, h), IndexError) # priority queue iterator 10587db96d56Sopenharmony_ci iter_except(d.popitem, KeyError) # non-blocking dict iterator 10597db96d56Sopenharmony_ci iter_except(d.popleft, IndexError) # non-blocking deque iterator 10607db96d56Sopenharmony_ci iter_except(q.get_nowait, Queue.Empty) # loop over a producer Queue 10617db96d56Sopenharmony_ci iter_except(s.pop, KeyError) # non-blocking set iterator 10627db96d56Sopenharmony_ci 10637db96d56Sopenharmony_ci """ 10647db96d56Sopenharmony_ci try: 10657db96d56Sopenharmony_ci if first is not None: 10667db96d56Sopenharmony_ci yield first() # For database APIs needing an initial cast to db.first() 10677db96d56Sopenharmony_ci while True: 10687db96d56Sopenharmony_ci yield func() 10697db96d56Sopenharmony_ci except exception: 10707db96d56Sopenharmony_ci pass 10717db96d56Sopenharmony_ci 10727db96d56Sopenharmony_ci def first_true(iterable, default=False, pred=None): 10737db96d56Sopenharmony_ci """Returns the first true value in the iterable. 10747db96d56Sopenharmony_ci 10757db96d56Sopenharmony_ci If no true value is found, returns *default* 10767db96d56Sopenharmony_ci 10777db96d56Sopenharmony_ci If *pred* is not None, returns the first item 10787db96d56Sopenharmony_ci for which pred(item) is true. 10797db96d56Sopenharmony_ci 10807db96d56Sopenharmony_ci """ 10817db96d56Sopenharmony_ci # first_true([a,b,c], x) --> a or b or c or x 10827db96d56Sopenharmony_ci # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x 10837db96d56Sopenharmony_ci return next(filter(pred, iterable), default) 10847db96d56Sopenharmony_ci 10857db96d56Sopenharmony_ci def nth_combination(iterable, r, index): 10867db96d56Sopenharmony_ci "Equivalent to list(combinations(iterable, r))[index]" 10877db96d56Sopenharmony_ci pool = tuple(iterable) 10887db96d56Sopenharmony_ci n = len(pool) 10897db96d56Sopenharmony_ci c = math.comb(n, r) 10907db96d56Sopenharmony_ci if index < 0: 10917db96d56Sopenharmony_ci index += c 10927db96d56Sopenharmony_ci if index < 0 or index >= c: 10937db96d56Sopenharmony_ci raise IndexError 10947db96d56Sopenharmony_ci result = [] 10957db96d56Sopenharmony_ci while r: 10967db96d56Sopenharmony_ci c, n, r = c*r//n, n-1, r-1 10977db96d56Sopenharmony_ci while index >= c: 10987db96d56Sopenharmony_ci index -= c 10997db96d56Sopenharmony_ci c, n = c*(n-r)//n, n-1 11007db96d56Sopenharmony_ci result.append(pool[-1-n]) 11017db96d56Sopenharmony_ci return tuple(result) 11027db96d56Sopenharmony_ci 11037db96d56Sopenharmony_ci.. doctest:: 11047db96d56Sopenharmony_ci :hide: 11057db96d56Sopenharmony_ci 11067db96d56Sopenharmony_ci These examples no longer appear in the docs but are guaranteed 11077db96d56Sopenharmony_ci to keep working. 11087db96d56Sopenharmony_ci 11097db96d56Sopenharmony_ci >>> amounts = [120.15, 764.05, 823.14] 11107db96d56Sopenharmony_ci >>> for checknum, amount in zip(count(1200), amounts): 11117db96d56Sopenharmony_ci ... print('Check %d is for $%.2f' % (checknum, amount)) 11127db96d56Sopenharmony_ci ... 11137db96d56Sopenharmony_ci Check 1200 is for $120.15 11147db96d56Sopenharmony_ci Check 1201 is for $764.05 11157db96d56Sopenharmony_ci Check 1202 is for $823.14 11167db96d56Sopenharmony_ci 11177db96d56Sopenharmony_ci >>> import operator 11187db96d56Sopenharmony_ci >>> for cube in map(operator.pow, range(1,4), repeat(3)): 11197db96d56Sopenharmony_ci ... print(cube) 11207db96d56Sopenharmony_ci ... 11217db96d56Sopenharmony_ci 1 11227db96d56Sopenharmony_ci 8 11237db96d56Sopenharmony_ci 27 11247db96d56Sopenharmony_ci 11257db96d56Sopenharmony_ci >>> reportlines = ['EuroPython', 'Roster', '', 'alex', '', 'laura', '', 'martin', '', 'walter', '', 'samuele'] 11267db96d56Sopenharmony_ci >>> for name in islice(reportlines, 3, None, 2): 11277db96d56Sopenharmony_ci ... print(name.title()) 11287db96d56Sopenharmony_ci ... 11297db96d56Sopenharmony_ci Alex 11307db96d56Sopenharmony_ci Laura 11317db96d56Sopenharmony_ci Martin 11327db96d56Sopenharmony_ci Walter 11337db96d56Sopenharmony_ci Samuele 11347db96d56Sopenharmony_ci 11357db96d56Sopenharmony_ci >>> from operator import itemgetter 11367db96d56Sopenharmony_ci >>> d = dict(a=1, b=2, c=1, d=2, e=1, f=2, g=3) 11377db96d56Sopenharmony_ci >>> di = sorted(sorted(d.items()), key=itemgetter(1)) 11387db96d56Sopenharmony_ci >>> for k, g in groupby(di, itemgetter(1)): 11397db96d56Sopenharmony_ci ... print(k, list(map(itemgetter(0), g))) 11407db96d56Sopenharmony_ci ... 11417db96d56Sopenharmony_ci 1 ['a', 'c', 'e'] 11427db96d56Sopenharmony_ci 2 ['b', 'd', 'f'] 11437db96d56Sopenharmony_ci 3 ['g'] 11447db96d56Sopenharmony_ci 11457db96d56Sopenharmony_ci # Find runs of consecutive numbers using groupby. The key to the solution 11467db96d56Sopenharmony_ci # is differencing with a range so that consecutive numbers all appear in 11477db96d56Sopenharmony_ci # same group. 11487db96d56Sopenharmony_ci >>> data = [ 1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28] 11497db96d56Sopenharmony_ci >>> for k, g in groupby(enumerate(data), lambda t:t[0]-t[1]): 11507db96d56Sopenharmony_ci ... print(list(map(operator.itemgetter(1), g))) 11517db96d56Sopenharmony_ci ... 11527db96d56Sopenharmony_ci [1] 11537db96d56Sopenharmony_ci [4, 5, 6] 11547db96d56Sopenharmony_ci [10] 11557db96d56Sopenharmony_ci [15, 16, 17, 18] 11567db96d56Sopenharmony_ci [22] 11577db96d56Sopenharmony_ci [25, 26, 27, 28] 11587db96d56Sopenharmony_ci 11597db96d56Sopenharmony_ci Now, we test all of the itertool recipes 11607db96d56Sopenharmony_ci 11617db96d56Sopenharmony_ci >>> take(10, count()) 11627db96d56Sopenharmony_ci [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 11637db96d56Sopenharmony_ci 11647db96d56Sopenharmony_ci >>> list(prepend(1, [2, 3, 4])) 11657db96d56Sopenharmony_ci [1, 2, 3, 4] 11667db96d56Sopenharmony_ci 11677db96d56Sopenharmony_ci >>> list(enumerate('abc')) 11687db96d56Sopenharmony_ci [(0, 'a'), (1, 'b'), (2, 'c')] 11697db96d56Sopenharmony_ci 11707db96d56Sopenharmony_ci >>> list(islice(tabulate(lambda x: 2*x), 4)) 11717db96d56Sopenharmony_ci [0, 2, 4, 6] 11727db96d56Sopenharmony_ci 11737db96d56Sopenharmony_ci >>> list(tail(3, 'ABCDEFG')) 11747db96d56Sopenharmony_ci ['E', 'F', 'G'] 11757db96d56Sopenharmony_ci 11767db96d56Sopenharmony_ci >>> it = iter(range(10)) 11777db96d56Sopenharmony_ci >>> consume(it, 3) 11787db96d56Sopenharmony_ci >>> next(it) 11797db96d56Sopenharmony_ci 3 11807db96d56Sopenharmony_ci >>> consume(it) 11817db96d56Sopenharmony_ci >>> next(it, 'Done') 11827db96d56Sopenharmony_ci 'Done' 11837db96d56Sopenharmony_ci 11847db96d56Sopenharmony_ci >>> nth('abcde', 3) 11857db96d56Sopenharmony_ci 'd' 11867db96d56Sopenharmony_ci 11877db96d56Sopenharmony_ci >>> nth('abcde', 9) is None 11887db96d56Sopenharmony_ci True 11897db96d56Sopenharmony_ci 11907db96d56Sopenharmony_ci >>> [all_equal(s) for s in ('', 'A', 'AAAA', 'AAAB', 'AAABA')] 11917db96d56Sopenharmony_ci [True, True, True, False, False] 11927db96d56Sopenharmony_ci 11937db96d56Sopenharmony_ci >>> quantify(range(99), lambda x: x%2==0) 11947db96d56Sopenharmony_ci 50 11957db96d56Sopenharmony_ci 11967db96d56Sopenharmony_ci >>> quantify([True, False, False, True, True]) 11977db96d56Sopenharmony_ci 3 11987db96d56Sopenharmony_ci 11997db96d56Sopenharmony_ci >>> quantify(range(12), pred=lambda x: x%2==1) 12007db96d56Sopenharmony_ci 6 12017db96d56Sopenharmony_ci 12027db96d56Sopenharmony_ci >>> a = [[1, 2, 3], [4, 5, 6]] 12037db96d56Sopenharmony_ci >>> list(flatten(a)) 12047db96d56Sopenharmony_ci [1, 2, 3, 4, 5, 6] 12057db96d56Sopenharmony_ci 12067db96d56Sopenharmony_ci >>> list(repeatfunc(pow, 5, 2, 3)) 12077db96d56Sopenharmony_ci [8, 8, 8, 8, 8] 12087db96d56Sopenharmony_ci 12097db96d56Sopenharmony_ci >>> take(5, map(int, repeatfunc(random.random))) 12107db96d56Sopenharmony_ci [0, 0, 0, 0, 0] 12117db96d56Sopenharmony_ci 12127db96d56Sopenharmony_ci >>> list(ncycles('abc', 3)) 12137db96d56Sopenharmony_ci ['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'] 12147db96d56Sopenharmony_ci 12157db96d56Sopenharmony_ci >>> sumprod([1,2,3], [4,5,6]) 12167db96d56Sopenharmony_ci 32 12177db96d56Sopenharmony_ci 12187db96d56Sopenharmony_ci >>> sum_of_squares([10, 20, 30]) 12197db96d56Sopenharmony_ci 1400 12207db96d56Sopenharmony_ci 12217db96d56Sopenharmony_ci >>> list(transpose([(1, 2, 3), (11, 22, 33)])) 12227db96d56Sopenharmony_ci [(1, 11), (2, 22), (3, 33)] 12237db96d56Sopenharmony_ci 12247db96d56Sopenharmony_ci >>> list(matmul([(7, 5), (3, 5)], [[2, 5], [7, 9]])) 12257db96d56Sopenharmony_ci [(49, 80), (41, 60)] 12267db96d56Sopenharmony_ci >>> list(matmul([[2, 5], [7, 9], [3, 4]], [[7, 11, 5, 4, 9], [3, 5, 2, 6, 3]])) 12277db96d56Sopenharmony_ci [(29, 47, 20, 38, 33), (76, 122, 53, 82, 90), (33, 53, 23, 36, 39)] 12287db96d56Sopenharmony_ci 12297db96d56Sopenharmony_ci >>> data = [20, 40, 24, 32, 20, 28, 16] 12307db96d56Sopenharmony_ci >>> list(convolve(data, [0.25, 0.25, 0.25, 0.25])) 12317db96d56Sopenharmony_ci [5.0, 15.0, 21.0, 29.0, 29.0, 26.0, 24.0, 16.0, 11.0, 4.0] 12327db96d56Sopenharmony_ci >>> list(convolve(data, [1, -1])) 12337db96d56Sopenharmony_ci [20, 20, -16, 8, -12, 8, -12, -16] 12347db96d56Sopenharmony_ci >>> list(convolve(data, [1, -2, 1])) 12357db96d56Sopenharmony_ci [20, 0, -36, 24, -20, 20, -20, -4, 16] 12367db96d56Sopenharmony_ci 12377db96d56Sopenharmony_ci >>> polynomial_from_roots([5, -4, 3]) 12387db96d56Sopenharmony_ci [1, -4, -17, 60] 12397db96d56Sopenharmony_ci >>> factored = lambda x: (x - 5) * (x + 4) * (x - 3) 12407db96d56Sopenharmony_ci >>> expanded = lambda x: x**3 -4*x**2 -17*x + 60 12417db96d56Sopenharmony_ci >>> all(factored(x) == expanded(x) for x in range(-10, 11)) 12427db96d56Sopenharmony_ci True 12437db96d56Sopenharmony_ci 12447db96d56Sopenharmony_ci >>> list(iter_index('AABCADEAF', 'A')) 12457db96d56Sopenharmony_ci [0, 1, 4, 7] 12467db96d56Sopenharmony_ci >>> list(iter_index('AABCADEAF', 'B')) 12477db96d56Sopenharmony_ci [2] 12487db96d56Sopenharmony_ci >>> list(iter_index('AABCADEAF', 'X')) 12497db96d56Sopenharmony_ci [] 12507db96d56Sopenharmony_ci >>> list(iter_index('', 'X')) 12517db96d56Sopenharmony_ci [] 12527db96d56Sopenharmony_ci >>> list(iter_index('AABCADEAF', 'A', 1)) 12537db96d56Sopenharmony_ci [1, 4, 7] 12547db96d56Sopenharmony_ci >>> list(iter_index(iter('AABCADEAF'), 'A', 1)) 12557db96d56Sopenharmony_ci [1, 4, 7] 12567db96d56Sopenharmony_ci >>> list(iter_index('AABCADEAF', 'A', 2)) 12577db96d56Sopenharmony_ci [4, 7] 12587db96d56Sopenharmony_ci >>> list(iter_index(iter('AABCADEAF'), 'A', 2)) 12597db96d56Sopenharmony_ci [4, 7] 12607db96d56Sopenharmony_ci >>> list(iter_index('AABCADEAF', 'A', 10)) 12617db96d56Sopenharmony_ci [] 12627db96d56Sopenharmony_ci >>> list(iter_index(iter('AABCADEAF'), 'A', 10)) 12637db96d56Sopenharmony_ci [] 12647db96d56Sopenharmony_ci 12657db96d56Sopenharmony_ci >>> list(sieve(30)) 12667db96d56Sopenharmony_ci [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] 12677db96d56Sopenharmony_ci >>> small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] 12687db96d56Sopenharmony_ci >>> all(list(sieve(n)) == [p for p in small_primes if p < n] for n in range(101)) 12697db96d56Sopenharmony_ci True 12707db96d56Sopenharmony_ci >>> len(list(sieve(100))) 12717db96d56Sopenharmony_ci 25 12727db96d56Sopenharmony_ci >>> len(list(sieve(1_000))) 12737db96d56Sopenharmony_ci 168 12747db96d56Sopenharmony_ci >>> len(list(sieve(10_000))) 12757db96d56Sopenharmony_ci 1229 12767db96d56Sopenharmony_ci >>> len(list(sieve(100_000))) 12777db96d56Sopenharmony_ci 9592 12787db96d56Sopenharmony_ci >>> len(list(sieve(1_000_000))) 12797db96d56Sopenharmony_ci 78498 12807db96d56Sopenharmony_ci >>> carmichael = {561, 1105, 1729, 2465, 2821, 6601, 8911} # https://oeis.org/A002997 12817db96d56Sopenharmony_ci >>> set(sieve(10_000)).isdisjoint(carmichael) 12827db96d56Sopenharmony_ci True 12837db96d56Sopenharmony_ci 12847db96d56Sopenharmony_ci >>> list(factor(0)) 12857db96d56Sopenharmony_ci [] 12867db96d56Sopenharmony_ci >>> list(factor(1)) 12877db96d56Sopenharmony_ci [] 12887db96d56Sopenharmony_ci >>> list(factor(2)) 12897db96d56Sopenharmony_ci [2] 12907db96d56Sopenharmony_ci >>> list(factor(3)) 12917db96d56Sopenharmony_ci [3] 12927db96d56Sopenharmony_ci >>> list(factor(4)) 12937db96d56Sopenharmony_ci [2, 2] 12947db96d56Sopenharmony_ci >>> list(factor(5)) 12957db96d56Sopenharmony_ci [5] 12967db96d56Sopenharmony_ci >>> list(factor(6)) 12977db96d56Sopenharmony_ci [2, 3] 12987db96d56Sopenharmony_ci >>> list(factor(7)) 12997db96d56Sopenharmony_ci [7] 13007db96d56Sopenharmony_ci >>> list(factor(8)) 13017db96d56Sopenharmony_ci [2, 2, 2] 13027db96d56Sopenharmony_ci >>> list(factor(9)) 13037db96d56Sopenharmony_ci [3, 3] 13047db96d56Sopenharmony_ci >>> list(factor(10)) 13057db96d56Sopenharmony_ci [2, 5] 13067db96d56Sopenharmony_ci >>> list(factor(128_884_753_939)) # large prime 13077db96d56Sopenharmony_ci [128884753939] 13087db96d56Sopenharmony_ci >>> list(factor(999953 * 999983)) # large semiprime 13097db96d56Sopenharmony_ci [999953, 999983] 13107db96d56Sopenharmony_ci >>> list(factor(6 ** 20)) == [2] * 20 + [3] * 20 # large power 13117db96d56Sopenharmony_ci True 13127db96d56Sopenharmony_ci >>> list(factor(909_909_090_909)) # large multiterm composite 13137db96d56Sopenharmony_ci [3, 3, 7, 13, 13, 751, 113797] 13147db96d56Sopenharmony_ci >>> math.prod([3, 3, 7, 13, 13, 751, 113797]) 13157db96d56Sopenharmony_ci 909909090909 13167db96d56Sopenharmony_ci >>> all(math.prod(factor(n)) == n for n in range(1, 2_000)) 13177db96d56Sopenharmony_ci True 13187db96d56Sopenharmony_ci >>> all(set(factor(n)) <= set(sieve(n+1)) for n in range(2_000)) 13197db96d56Sopenharmony_ci True 13207db96d56Sopenharmony_ci >>> all(list(factor(n)) == sorted(factor(n)) for n in range(2_000)) 13217db96d56Sopenharmony_ci True 13227db96d56Sopenharmony_ci 13237db96d56Sopenharmony_ci >>> list(flatten([('a', 'b'), (), ('c', 'd', 'e'), ('f',), ('g', 'h', 'i')])) 13247db96d56Sopenharmony_ci ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] 13257db96d56Sopenharmony_ci 13267db96d56Sopenharmony_ci >>> random.seed(85753098575309) 13277db96d56Sopenharmony_ci >>> list(repeatfunc(random.random, 3)) 13287db96d56Sopenharmony_ci [0.16370491282496968, 0.45889608687313455, 0.3747076837820118] 13297db96d56Sopenharmony_ci >>> list(repeatfunc(chr, 3, 65)) 13307db96d56Sopenharmony_ci ['A', 'A', 'A'] 13317db96d56Sopenharmony_ci >>> list(repeatfunc(pow, 3, 2, 5)) 13327db96d56Sopenharmony_ci [32, 32, 32] 13337db96d56Sopenharmony_ci 13347db96d56Sopenharmony_ci >>> list(grouper('abcdefg', 3, fillvalue='x')) 13357db96d56Sopenharmony_ci [('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'x', 'x')] 13367db96d56Sopenharmony_ci 13377db96d56Sopenharmony_ci >>> it = grouper('abcdefg', 3, incomplete='strict') 13387db96d56Sopenharmony_ci >>> next(it) 13397db96d56Sopenharmony_ci ('a', 'b', 'c') 13407db96d56Sopenharmony_ci >>> next(it) 13417db96d56Sopenharmony_ci ('d', 'e', 'f') 13427db96d56Sopenharmony_ci >>> next(it) 13437db96d56Sopenharmony_ci Traceback (most recent call last): 13447db96d56Sopenharmony_ci ... 13457db96d56Sopenharmony_ci ValueError: zip() argument 2 is shorter than argument 1 13467db96d56Sopenharmony_ci 13477db96d56Sopenharmony_ci >>> list(grouper('abcdefg', n=3, incomplete='ignore')) 13487db96d56Sopenharmony_ci [('a', 'b', 'c'), ('d', 'e', 'f')] 13497db96d56Sopenharmony_ci 13507db96d56Sopenharmony_ci >>> list(batched('ABCDEFG', 3)) 13517db96d56Sopenharmony_ci [('A', 'B', 'C'), ('D', 'E', 'F'), ('G',)] 13527db96d56Sopenharmony_ci >>> list(batched('ABCDEF', 3)) 13537db96d56Sopenharmony_ci [('A', 'B', 'C'), ('D', 'E', 'F')] 13547db96d56Sopenharmony_ci >>> list(batched('ABCDE', 3)) 13557db96d56Sopenharmony_ci [('A', 'B', 'C'), ('D', 'E')] 13567db96d56Sopenharmony_ci >>> list(batched('ABCD', 3)) 13577db96d56Sopenharmony_ci [('A', 'B', 'C'), ('D',)] 13587db96d56Sopenharmony_ci >>> list(batched('ABC', 3)) 13597db96d56Sopenharmony_ci [('A', 'B', 'C')] 13607db96d56Sopenharmony_ci >>> list(batched('AB', 3)) 13617db96d56Sopenharmony_ci [('A', 'B')] 13627db96d56Sopenharmony_ci >>> list(batched('A', 3)) 13637db96d56Sopenharmony_ci [('A',)] 13647db96d56Sopenharmony_ci >>> list(batched('', 3)) 13657db96d56Sopenharmony_ci [] 13667db96d56Sopenharmony_ci >>> list(batched('ABCDEFG', 2)) 13677db96d56Sopenharmony_ci [('A', 'B'), ('C', 'D'), ('E', 'F'), ('G',)] 13687db96d56Sopenharmony_ci >>> list(batched('ABCDEFG', 1)) 13697db96d56Sopenharmony_ci [('A',), ('B',), ('C',), ('D',), ('E',), ('F',), ('G',)] 13707db96d56Sopenharmony_ci >>> s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 13717db96d56Sopenharmony_ci >>> all(list(flatten(batched(s[:n], 5))) == list(s[:n]) for n in range(len(s))) 13727db96d56Sopenharmony_ci True 13737db96d56Sopenharmony_ci 13747db96d56Sopenharmony_ci >>> list(triplewise('ABCDEFG')) 13757db96d56Sopenharmony_ci [('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E'), ('D', 'E', 'F'), ('E', 'F', 'G')] 13767db96d56Sopenharmony_ci 13777db96d56Sopenharmony_ci >>> list(sliding_window('ABCDEFG', 4)) 13787db96d56Sopenharmony_ci [('A', 'B', 'C', 'D'), ('B', 'C', 'D', 'E'), ('C', 'D', 'E', 'F'), ('D', 'E', 'F', 'G')] 13797db96d56Sopenharmony_ci 13807db96d56Sopenharmony_ci >>> list(roundrobin('abc', 'd', 'ef')) 13817db96d56Sopenharmony_ci ['a', 'd', 'e', 'b', 'f', 'c'] 13827db96d56Sopenharmony_ci 13837db96d56Sopenharmony_ci >>> def is_odd(x): 13847db96d56Sopenharmony_ci ... return x % 2 == 1 13857db96d56Sopenharmony_ci 13867db96d56Sopenharmony_ci >>> evens, odds = partition(is_odd, range(10)) 13877db96d56Sopenharmony_ci >>> list(evens) 13887db96d56Sopenharmony_ci [0, 2, 4, 6, 8] 13897db96d56Sopenharmony_ci >>> list(odds) 13907db96d56Sopenharmony_ci [1, 3, 5, 7, 9] 13917db96d56Sopenharmony_ci 13927db96d56Sopenharmony_ci >>> it = iter('ABCdEfGhI') 13937db96d56Sopenharmony_ci >>> all_upper, remainder = before_and_after(str.isupper, it) 13947db96d56Sopenharmony_ci >>> ''.join(all_upper) 13957db96d56Sopenharmony_ci 'ABC' 13967db96d56Sopenharmony_ci >>> ''.join(remainder) 13977db96d56Sopenharmony_ci 'dEfGhI' 13987db96d56Sopenharmony_ci 13997db96d56Sopenharmony_ci >>> list(subslices('ABCD')) 14007db96d56Sopenharmony_ci ['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D'] 14017db96d56Sopenharmony_ci 14027db96d56Sopenharmony_ci >>> list(powerset([1,2,3])) 14037db96d56Sopenharmony_ci [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] 14047db96d56Sopenharmony_ci 14057db96d56Sopenharmony_ci >>> all(len(list(powerset(range(n)))) == 2**n for n in range(18)) 14067db96d56Sopenharmony_ci True 14077db96d56Sopenharmony_ci 14087db96d56Sopenharmony_ci >>> list(powerset('abcde')) == sorted(sorted(set(powerset('abcde'))), key=len) 14097db96d56Sopenharmony_ci True 14107db96d56Sopenharmony_ci 14117db96d56Sopenharmony_ci >>> list(unique_everseen('AAAABBBCCDAABBB')) 14127db96d56Sopenharmony_ci ['A', 'B', 'C', 'D'] 14137db96d56Sopenharmony_ci >>> list(unique_everseen('ABBCcAD', str.lower)) 14147db96d56Sopenharmony_ci ['A', 'B', 'C', 'D'] 14157db96d56Sopenharmony_ci >>> list(unique_everseen('ABBcCAD', str.lower)) 14167db96d56Sopenharmony_ci ['A', 'B', 'c', 'D'] 14177db96d56Sopenharmony_ci 14187db96d56Sopenharmony_ci >>> list(unique_justseen('AAAABBBCCDAABBB')) 14197db96d56Sopenharmony_ci ['A', 'B', 'C', 'D', 'A', 'B'] 14207db96d56Sopenharmony_ci >>> list(unique_justseen('ABBCcAD', str.lower)) 14217db96d56Sopenharmony_ci ['A', 'B', 'C', 'A', 'D'] 14227db96d56Sopenharmony_ci >>> list(unique_justseen('ABBcCAD', str.lower)) 14237db96d56Sopenharmony_ci ['A', 'B', 'c', 'A', 'D'] 14247db96d56Sopenharmony_ci 14257db96d56Sopenharmony_ci >>> d = dict(a=1, b=2, c=3) 14267db96d56Sopenharmony_ci >>> it = iter_except(d.popitem, KeyError) 14277db96d56Sopenharmony_ci >>> d['d'] = 4 14287db96d56Sopenharmony_ci >>> next(it) 14297db96d56Sopenharmony_ci ('d', 4) 14307db96d56Sopenharmony_ci >>> next(it) 14317db96d56Sopenharmony_ci ('c', 3) 14327db96d56Sopenharmony_ci >>> next(it) 14337db96d56Sopenharmony_ci ('b', 2) 14347db96d56Sopenharmony_ci >>> d['e'] = 5 14357db96d56Sopenharmony_ci >>> next(it) 14367db96d56Sopenharmony_ci ('e', 5) 14377db96d56Sopenharmony_ci >>> next(it) 14387db96d56Sopenharmony_ci ('a', 1) 14397db96d56Sopenharmony_ci >>> next(it, 'empty') 14407db96d56Sopenharmony_ci 'empty' 14417db96d56Sopenharmony_ci 14427db96d56Sopenharmony_ci >>> first_true('ABC0DEF1', '9', str.isdigit) 14437db96d56Sopenharmony_ci '0' 14447db96d56Sopenharmony_ci 14457db96d56Sopenharmony_ci >>> population = 'ABCDEFGH' 14467db96d56Sopenharmony_ci >>> for r in range(len(population) + 1): 14477db96d56Sopenharmony_ci ... seq = list(combinations(population, r)) 14487db96d56Sopenharmony_ci ... for i in range(len(seq)): 14497db96d56Sopenharmony_ci ... assert nth_combination(population, r, i) == seq[i] 14507db96d56Sopenharmony_ci ... for i in range(-len(seq), 0): 14517db96d56Sopenharmony_ci ... assert nth_combination(population, r, i) == seq[i] 14527db96d56Sopenharmony_ci 14537db96d56Sopenharmony_ci >>> iterable = 'abcde' 14547db96d56Sopenharmony_ci >>> r = 3 14557db96d56Sopenharmony_ci >>> combos = list(combinations(iterable, r)) 14567db96d56Sopenharmony_ci >>> all(nth_combination(iterable, r, i) == comb for i, comb in enumerate(combos)) 14577db96d56Sopenharmony_ci True 1458