mirror of https://github.com/python/cpython
Minor improvements to the itertools documentation (gh-116833)
This commit is contained in:
parent
c432df6d56
commit
ab9e322ae1
|
@ -41,9 +41,9 @@ operator can be mapped across two vectors to form an efficient dot-product:
|
|||
================== ================= ================================================= =========================================
|
||||
Iterator Arguments Results Example
|
||||
================== ================= ================================================= =========================================
|
||||
:func:`count` [start[, step]] start, start+step, start+2*step, ... ``count(10) --> 10 11 12 13 14 ...``
|
||||
:func:`cycle` p p0, p1, ... plast, p0, p1, ... ``cycle('ABCD') --> A B C D A B C D ...``
|
||||
:func:`repeat` elem [,n] elem, elem, elem, ... endlessly or up to n times ``repeat(10, 3) --> 10 10 10``
|
||||
:func:`count` [start[, step]] start, start+step, start+2*step, ... ``count(10) → 10 11 12 13 14 ...``
|
||||
:func:`cycle` p p0, p1, ... plast, p0, p1, ... ``cycle('ABCD') → A B C D A B C D ...``
|
||||
:func:`repeat` elem [,n] elem, elem, elem, ... endlessly or up to n times ``repeat(10, 3) → 10 10 10``
|
||||
================== ================= ================================================= =========================================
|
||||
|
||||
**Iterators terminating on the shortest input sequence:**
|
||||
|
@ -51,20 +51,20 @@ Iterator Arguments Results
|
|||
============================ ============================ ================================================= =============================================================
|
||||
Iterator Arguments Results Example
|
||||
============================ ============================ ================================================= =============================================================
|
||||
:func:`accumulate` p [,func] p0, p0+p1, p0+p1+p2, ... ``accumulate([1,2,3,4,5]) --> 1 3 6 10 15``
|
||||
:func:`batched` p, n (p0, p1, ..., p_n-1), ... ``batched('ABCDEFG', n=3) --> ABC DEF G``
|
||||
:func:`chain` p, q, ... p0, p1, ... plast, q0, q1, ... ``chain('ABC', 'DEF') --> A B C D E F``
|
||||
:func:`chain.from_iterable` iterable p0, p1, ... plast, q0, q1, ... ``chain.from_iterable(['ABC', 'DEF']) --> A B C D E F``
|
||||
: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``
|
||||
:func:`dropwhile` predicate, seq seq[n], seq[n+1], starting when predicate fails ``dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1``
|
||||
:func:`filterfalse` predicate, seq elements of seq where predicate(elem) fails ``filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8``
|
||||
:func:`accumulate` p [,func] p0, p0+p1, p0+p1+p2, ... ``accumulate([1,2,3,4,5]) → 1 3 6 10 15``
|
||||
:func:`batched` p, n (p0, p1, ..., p_n-1), ... ``batched('ABCDEFG', n=3) → ABC DEF G``
|
||||
:func:`chain` p, q, ... p0, p1, ... plast, q0, q1, ... ``chain('ABC', 'DEF') → A B C D E F``
|
||||
:func:`chain.from_iterable` iterable p0, p1, ... plast, q0, q1, ... ``chain.from_iterable(['ABC', 'DEF']) → A B C D E F``
|
||||
: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``
|
||||
:func:`dropwhile` predicate, seq seq[n], seq[n+1], starting when predicate fails ``dropwhile(lambda x: x<5, [1,4,6,4,1]) → 6 4 1``
|
||||
:func:`filterfalse` predicate, seq elements of seq where predicate(elem) fails ``filterfalse(lambda x: x%2, range(10)) → 0 2 4 6 8``
|
||||
:func:`groupby` iterable[, key] sub-iterators grouped by value of key(v)
|
||||
:func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] ``islice('ABCDEFG', 2, None) --> C D E F G``
|
||||
:func:`pairwise` iterable (p[0], p[1]), (p[1], p[2]) ``pairwise('ABCDEFG') --> AB BC CD DE EF FG``
|
||||
:func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... ``starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000``
|
||||
:func:`takewhile` predicate, seq seq[0], seq[1], until predicate fails ``takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4``
|
||||
:func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] ``islice('ABCDEFG', 2, None) → C D E F G``
|
||||
:func:`pairwise` iterable (p[0], p[1]), (p[1], p[2]) ``pairwise('ABCDEFG') → AB BC CD DE EF FG``
|
||||
:func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... ``starmap(pow, [(2,5), (3,2), (10,3)]) → 32 9 1000``
|
||||
:func:`takewhile` predicate, seq seq[0], seq[1], until predicate fails ``takewhile(lambda x: x<5, [1,4,6,4,1]) → 1 4``
|
||||
:func:`tee` it, n it1, it2, ... itn splits one iterator into n
|
||||
:func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-``
|
||||
:func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``zip_longest('ABCD', 'xy', fillvalue='-') → Ax By C- D-``
|
||||
============================ ============================ ================================================= =============================================================
|
||||
|
||||
**Combinatoric iterators:**
|
||||
|
@ -84,7 +84,7 @@ Examples Results
|
|||
``product('ABCD', repeat=2)`` ``AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD``
|
||||
``permutations('ABCD', 2)`` ``AB AC AD BA BC BD CA CB CD DA DB DC``
|
||||
``combinations('ABCD', 2)`` ``AB AC AD BC BD CD``
|
||||
``combinations_with_replacement('ABCD', 2)`` ``AA AB AC AD BB BC BD CC CD DD``
|
||||
``combinations_with_replacement('ABCD', 2)`` ``AA AB AC AD BB BC BD CC CD DD``
|
||||
============================================== =============================================================
|
||||
|
||||
|
||||
|
@ -119,9 +119,9 @@ loops that truncate the stream.
|
|||
|
||||
def accumulate(iterable, func=operator.add, *, initial=None):
|
||||
'Return running totals'
|
||||
# accumulate([1,2,3,4,5]) --> 1 3 6 10 15
|
||||
# accumulate([1,2,3,4,5], initial=100) --> 100 101 103 106 110 115
|
||||
# accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
|
||||
# accumulate([1,2,3,4,5]) → 1 3 6 10 15
|
||||
# accumulate([1,2,3,4,5], initial=100) → 100 101 103 106 110 115
|
||||
# accumulate([1,2,3,4,5], operator.mul) → 1 2 6 24 120
|
||||
it = iter(iterable)
|
||||
total = initial
|
||||
if initial is None:
|
||||
|
@ -194,7 +194,7 @@ loops that truncate the stream.
|
|||
Roughly equivalent to::
|
||||
|
||||
def batched(iterable, n, *, strict=False):
|
||||
# batched('ABCDEFG', 3) --> ABC DEF G
|
||||
# batched('ABCDEFG', 3) → ABC DEF G
|
||||
if n < 1:
|
||||
raise ValueError('n must be at least one')
|
||||
it = iter(iterable)
|
||||
|
@ -217,7 +217,7 @@ loops that truncate the stream.
|
|||
Roughly equivalent to::
|
||||
|
||||
def chain(*iterables):
|
||||
# chain('ABC', 'DEF') --> A B C D E F
|
||||
# chain('ABC', 'DEF') → A B C D E F
|
||||
for it in iterables:
|
||||
for element in it:
|
||||
yield element
|
||||
|
@ -229,7 +229,7 @@ loops that truncate the stream.
|
|||
single iterable argument that is evaluated lazily. Roughly equivalent to::
|
||||
|
||||
def from_iterable(iterables):
|
||||
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
|
||||
# chain.from_iterable(['ABC', 'DEF']) → A B C D E F
|
||||
for it in iterables:
|
||||
for element in it:
|
||||
yield element
|
||||
|
@ -250,8 +250,8 @@ loops that truncate the stream.
|
|||
Roughly equivalent to::
|
||||
|
||||
def combinations(iterable, r):
|
||||
# combinations('ABCD', 2) --> AB AC AD BC BD CD
|
||||
# combinations(range(4), 3) --> 012 013 023 123
|
||||
# combinations('ABCD', 2) → AB AC AD BC BD CD
|
||||
# combinations(range(4), 3) → 012 013 023 123
|
||||
pool = tuple(iterable)
|
||||
n = len(pool)
|
||||
if r > n:
|
||||
|
@ -299,7 +299,7 @@ loops that truncate the stream.
|
|||
Roughly equivalent to::
|
||||
|
||||
def combinations_with_replacement(iterable, r):
|
||||
# combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
|
||||
# combinations_with_replacement('ABC', 2) → AA AB AC BB BC CC
|
||||
pool = tuple(iterable)
|
||||
n = len(pool)
|
||||
if not n and r:
|
||||
|
@ -339,7 +339,7 @@ loops that truncate the stream.
|
|||
Roughly equivalent to::
|
||||
|
||||
def compress(data, selectors):
|
||||
# compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
|
||||
# compress('ABCDEF', [1,0,1,0,1,1]) → A C E F
|
||||
return (d for d, s in zip(data, selectors) if s)
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
@ -352,8 +352,8 @@ loops that truncate the stream.
|
|||
Also, used with :func:`zip` to add sequence numbers. Roughly equivalent to::
|
||||
|
||||
def count(start=0, step=1):
|
||||
# count(10) --> 10 11 12 13 14 ...
|
||||
# count(2.5, 0.5) --> 2.5 3.0 3.5 ...
|
||||
# count(10) → 10 11 12 13 14 ...
|
||||
# count(2.5, 0.5) → 2.5 3.0 3.5 ...
|
||||
n = start
|
||||
while True:
|
||||
yield n
|
||||
|
@ -373,7 +373,7 @@ loops that truncate the stream.
|
|||
indefinitely. Roughly equivalent to::
|
||||
|
||||
def cycle(iterable):
|
||||
# cycle('ABCD') --> A B C D A B C D A B C D ...
|
||||
# cycle('ABCD') → A B C D A B C D A B C D ...
|
||||
saved = []
|
||||
for element in iterable:
|
||||
yield element
|
||||
|
@ -394,7 +394,7 @@ loops that truncate the stream.
|
|||
start-up time. Roughly equivalent to::
|
||||
|
||||
def dropwhile(predicate, iterable):
|
||||
# dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
|
||||
# dropwhile(lambda x: x<5, [1,4,6,4,1]) → 6 4 1
|
||||
iterable = iter(iterable)
|
||||
for x in iterable:
|
||||
if not predicate(x):
|
||||
|
@ -410,7 +410,7 @@ loops that truncate the stream.
|
|||
that are false. Roughly equivalent to::
|
||||
|
||||
def filterfalse(predicate, iterable):
|
||||
# filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8
|
||||
# filterfalse(lambda x: x%2, range(10)) → 0 2 4 6 8
|
||||
if predicate is None:
|
||||
predicate = bool
|
||||
for x in iterable:
|
||||
|
@ -447,8 +447,8 @@ loops that truncate the stream.
|
|||
:func:`groupby` is roughly equivalent to::
|
||||
|
||||
class groupby:
|
||||
# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
|
||||
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
|
||||
# [k for k, g in groupby('AAAABBBCCDAABBB')] → A B C D A B
|
||||
# [list(g) for k, g in groupby('AAAABBBCCD')] → AAAA BBB CC D
|
||||
|
||||
def __init__(self, iterable, key=None):
|
||||
if key is None:
|
||||
|
@ -499,10 +499,10 @@ loops that truncate the stream.
|
|||
Roughly equivalent to::
|
||||
|
||||
def islice(iterable, *args):
|
||||
# islice('ABCDEFG', 2) --> A B
|
||||
# islice('ABCDEFG', 2, 4) --> C D
|
||||
# islice('ABCDEFG', 2, None) --> C D E F G
|
||||
# islice('ABCDEFG', 0, None, 2) --> A C E G
|
||||
# islice('ABCDEFG', 2) → A B
|
||||
# islice('ABCDEFG', 2, 4) → C D
|
||||
# islice('ABCDEFG', 2, None) → C D E F G
|
||||
# islice('ABCDEFG', 0, None, 2) → A C E G
|
||||
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))
|
||||
|
@ -535,10 +535,12 @@ loops that truncate the stream.
|
|||
Roughly equivalent to::
|
||||
|
||||
def pairwise(iterable):
|
||||
# pairwise('ABCDEFG') --> AB BC CD DE EF FG
|
||||
a, b = tee(iterable)
|
||||
next(b, None)
|
||||
return zip(a, b)
|
||||
# pairwise('ABCDEFG') → AB BC CD DE EF FG
|
||||
iterator = iter(iterable)
|
||||
a = next(iterator, None)
|
||||
for b in iterator:
|
||||
yield a, b
|
||||
a = b
|
||||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
|
@ -562,8 +564,8 @@ loops that truncate the stream.
|
|||
Roughly equivalent to::
|
||||
|
||||
def permutations(iterable, r=None):
|
||||
# permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
|
||||
# permutations(range(3)) --> 012 021 102 120 201 210
|
||||
# permutations('ABCD', 2) → AB AC AD BA BC BD CA CB CD DA DB DC
|
||||
# permutations(range(3)) → 012 021 102 120 201 210
|
||||
pool = tuple(iterable)
|
||||
n = len(pool)
|
||||
r = n if r is None else r
|
||||
|
@ -621,8 +623,8 @@ loops that truncate the stream.
|
|||
actual implementation does not build up intermediate results in memory::
|
||||
|
||||
def product(*args, repeat=1):
|
||||
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
|
||||
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
|
||||
# product('ABCD', 'xy') → Ax Ay Bx By Cx Cy Dx Dy
|
||||
# product(range(2), repeat=3) → 000 001 010 011 100 101 110 111
|
||||
pools = [tuple(pool) for pool in args] * repeat
|
||||
result = [[]]
|
||||
for pool in pools:
|
||||
|
@ -642,7 +644,7 @@ loops that truncate the stream.
|
|||
Roughly equivalent to::
|
||||
|
||||
def repeat(object, times=None):
|
||||
# repeat(10, 3) --> 10 10 10
|
||||
# repeat(10, 3) → 10 10 10
|
||||
if times is None:
|
||||
while True:
|
||||
yield object
|
||||
|
@ -670,7 +672,7 @@ loops that truncate the stream.
|
|||
equivalent to::
|
||||
|
||||
def starmap(function, iterable):
|
||||
# starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000
|
||||
# starmap(pow, [(2,5), (3,2), (10,3)]) → 32 9 1000
|
||||
for args in iterable:
|
||||
yield function(*args)
|
||||
|
||||
|
@ -681,7 +683,7 @@ loops that truncate the stream.
|
|||
predicate is true. Roughly equivalent to::
|
||||
|
||||
def takewhile(predicate, iterable):
|
||||
# takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
|
||||
# takewhile(lambda x: x<5, [1,4,6,4,1]) → 1 4
|
||||
for x in iterable:
|
||||
if predicate(x):
|
||||
yield x
|
||||
|
@ -741,7 +743,7 @@ loops that truncate the stream.
|
|||
Iteration continues until the longest iterable is exhausted. Roughly equivalent to::
|
||||
|
||||
def zip_longest(*args, fillvalue=None):
|
||||
# zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
|
||||
# zip_longest('ABCD', 'xy', fillvalue='-') → Ax By C- D-
|
||||
iterators = [iter(it) for it in args]
|
||||
num_active = len(iterators)
|
||||
if not num_active:
|
||||
|
@ -816,7 +818,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
|
|||
|
||||
def prepend(value, iterable):
|
||||
"Prepend a single value in front of an iterable."
|
||||
# prepend(1, [2, 3, 4]) --> 1 2 3 4
|
||||
# prepend(1, [2, 3, 4]) → 1 2 3 4
|
||||
return chain([value], iterable)
|
||||
|
||||
def tabulate(function, start=0):
|
||||
|
@ -842,7 +844,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
|
|||
|
||||
def tail(n, iterable):
|
||||
"Return an iterator over the last n items."
|
||||
# tail(3, 'ABCDEFG') --> E F G
|
||||
# tail(3, 'ABCDEFG') → E F G
|
||||
return iter(collections.deque(iterable, maxlen=n))
|
||||
|
||||
def consume(iterator, n=None):
|
||||
|
@ -865,26 +867,27 @@ and :term:`generators <generator>` which incur interpreter overhead.
|
|||
|
||||
def first_true(iterable, default=False, predicate=None):
|
||||
"Returns the first true value or the *default* if there is no true value."
|
||||
# first_true([a,b,c], x) --> a or b or c or x
|
||||
# first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
|
||||
# first_true([a,b,c], x) → a or b or c or x
|
||||
# first_true([a,b], x, f) → a if f(a) else b if f(b) else x
|
||||
return next(filter(predicate, iterable), default)
|
||||
|
||||
def all_equal(iterable, key=None):
|
||||
"Returns True if all the elements are equal to each other."
|
||||
# all_equal('4٤໔4৪', key=int) → True
|
||||
return len(take(2, groupby(iterable, key))) <= 1
|
||||
|
||||
def unique_justseen(iterable, key=None):
|
||||
"List unique elements, preserving order. Remember only the element just seen."
|
||||
# unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
|
||||
# unique_justseen('ABBcCAD', str.casefold) --> A B c A D
|
||||
# unique_justseen('AAAABBBCCDAABBB') → A B C D A B
|
||||
# unique_justseen('ABBcCAD', str.casefold) → A B c A D
|
||||
if key is None:
|
||||
return map(operator.itemgetter(0), groupby(iterable))
|
||||
return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
|
||||
|
||||
def unique_everseen(iterable, key=None):
|
||||
"List unique elements, preserving order. Remember all elements ever seen."
|
||||
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
|
||||
# unique_everseen('ABBcCAD', str.casefold) --> A B c D
|
||||
# unique_everseen('AAAABBBCCDAABBB') → A B C D
|
||||
# unique_everseen('ABBcCAD', str.casefold) → A B c D
|
||||
seen = set()
|
||||
if key is None:
|
||||
for element in filterfalse(seen.__contains__, iterable):
|
||||
|
@ -899,7 +902,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
|
|||
|
||||
def sliding_window(iterable, n):
|
||||
"Collect data into overlapping fixed-length chunks or blocks."
|
||||
# sliding_window('ABCDEFG', 4) --> ABCD BCDE CDEF DEFG
|
||||
# sliding_window('ABCDEFG', 4) → ABCD BCDE CDEF DEFG
|
||||
it = iter(iterable)
|
||||
window = collections.deque(islice(it, n-1), maxlen=n)
|
||||
for x in it:
|
||||
|
@ -908,9 +911,9 @@ and :term:`generators <generator>` which incur interpreter overhead.
|
|||
|
||||
def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
|
||||
"Collect data into non-overlapping fixed-length chunks or blocks."
|
||||
# grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
|
||||
# grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
|
||||
# grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
|
||||
# grouper('ABCDEFG', 3, fillvalue='x') → ABC DEF Gxx
|
||||
# grouper('ABCDEFG', 3, incomplete='strict') → ABC DEF ValueError
|
||||
# grouper('ABCDEFG', 3, incomplete='ignore') → ABC DEF
|
||||
iterators = [iter(iterable)] * n
|
||||
match incomplete:
|
||||
case 'fill':
|
||||
|
@ -924,7 +927,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
|
|||
|
||||
def roundrobin(*iterables):
|
||||
"Visit input iterables in a cycle until each is exhausted."
|
||||
# roundrobin('ABC', 'D', 'EF') --> A D E B F C
|
||||
# roundrobin('ABC', 'D', 'EF') → A D E B F C
|
||||
# Algorithm credited to George Sakkis
|
||||
iterators = map(iter, iterables)
|
||||
for num_active in range(len(iterables), 0, -1):
|
||||
|
@ -936,19 +939,19 @@ and :term:`generators <generator>` which incur interpreter overhead.
|
|||
|
||||
If *predicate* is slow, consider wrapping it with functools.lru_cache().
|
||||
"""
|
||||
# partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9
|
||||
# partition(is_odd, range(10)) → 0 2 4 6 8 and 1 3 5 7 9
|
||||
t1, t2 = tee(iterable)
|
||||
return filterfalse(predicate, t1), filter(predicate, t2)
|
||||
|
||||
def subslices(seq):
|
||||
"Return all contiguous non-empty subslices of a sequence."
|
||||
# subslices('ABCD') --> A AB ABC ABCD B BC BCD C CD D
|
||||
# subslices('ABCD') → A AB ABC ABCD B BC BCD C CD D
|
||||
slices = starmap(slice, combinations(range(len(seq) + 1), 2))
|
||||
return map(operator.getitem, repeat(seq), slices)
|
||||
|
||||
def iter_index(iterable, value, start=0, stop=None):
|
||||
"Return indices where a value occurs in a sequence or iterable."
|
||||
# iter_index('AABCADEAF', 'A') --> 0 1 4 7
|
||||
# iter_index('AABCADEAF', 'A') → 0 1 4 7
|
||||
seq_index = getattr(iterable, 'index', None)
|
||||
if seq_index is None:
|
||||
# Path for general iterables
|
||||
|
@ -972,7 +975,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
|
|||
|
||||
Converts a call-until-exception interface to an iterator interface.
|
||||
"""
|
||||
# iter_except(d.popitem, KeyError) --> non-blocking dictionary iterator
|
||||
# iter_except(d.popitem, KeyError) → non-blocking dictionary iterator
|
||||
try:
|
||||
if first is not None:
|
||||
yield first()
|
||||
|
@ -987,28 +990,28 @@ The following recipes have a more mathematical flavor:
|
|||
.. testcode::
|
||||
|
||||
def powerset(iterable):
|
||||
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
|
||||
"powerset([1,2,3]) → () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
|
||||
s = list(iterable)
|
||||
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
|
||||
|
||||
def sum_of_squares(iterable):
|
||||
"Add up the squares of the input values."
|
||||
# sum_of_squares([10, 20, 30]) --> 1400
|
||||
# sum_of_squares([10, 20, 30]) → 1400
|
||||
return math.sumprod(*tee(iterable))
|
||||
|
||||
def reshape(matrix, cols):
|
||||
"Reshape a 2-D matrix to have a given number of columns."
|
||||
# reshape([(0, 1), (2, 3), (4, 5)], 3) --> (0, 1, 2), (3, 4, 5)
|
||||
# reshape([(0, 1), (2, 3), (4, 5)], 3) → (0, 1, 2), (3, 4, 5)
|
||||
return batched(chain.from_iterable(matrix), cols, strict=True)
|
||||
|
||||
def transpose(matrix):
|
||||
"Swap the rows and columns of a 2-D matrix."
|
||||
# transpose([(1, 2, 3), (11, 22, 33)]) --> (1, 11) (2, 22) (3, 33)
|
||||
# transpose([(1, 2, 3), (11, 22, 33)]) → (1, 11) (2, 22) (3, 33)
|
||||
return zip(*matrix, strict=True)
|
||||
|
||||
def matmul(m1, m2):
|
||||
"Multiply two matrices."
|
||||
# matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]) --> (49, 80), (41, 60)
|
||||
# matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]) → (49, 80), (41, 60)
|
||||
n = len(m2[0])
|
||||
return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
|
||||
|
||||
|
@ -1023,10 +1026,10 @@ The following recipes have a more mathematical flavor:
|
|||
Article: https://betterexplained.com/articles/intuitive-convolution/
|
||||
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
|
||||
"""
|
||||
# convolve([1, -1, -20], [1, -3]) --> 1 -4 -17 60
|
||||
# convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
|
||||
# convolve(data, [1/2, 0, -1/2]) --> 1st derivative estimate
|
||||
# convolve(data, [1, -2, 1]) --> 2nd derivative estimate
|
||||
# convolve([1, -1, -20], [1, -3]) → 1 -4 -17 60
|
||||
# convolve(data, [0.25, 0.25, 0.25, 0.25]) → Moving average (blur)
|
||||
# convolve(data, [1/2, 0, -1/2]) → 1st derivative estimate
|
||||
# convolve(data, [1, -2, 1]) → 2nd derivative estimate
|
||||
kernel = tuple(kernel)[::-1]
|
||||
n = len(kernel)
|
||||
padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
|
||||
|
@ -1038,7 +1041,7 @@ The following recipes have a more mathematical flavor:
|
|||
|
||||
(x - 5) (x + 4) (x - 3) expands to: x³ -4x² -17x + 60
|
||||
"""
|
||||
# polynomial_from_roots([5, -4, 3]) --> [1, -4, -17, 60]
|
||||
# polynomial_from_roots([5, -4, 3]) → [1, -4, -17, 60]
|
||||
factors = zip(repeat(1), map(operator.neg, roots))
|
||||
return list(functools.reduce(convolve, factors, [1]))
|
||||
|
||||
|
@ -1048,7 +1051,7 @@ The following recipes have a more mathematical flavor:
|
|||
Computes with better numeric stability than Horner's method.
|
||||
"""
|
||||
# Evaluate x³ -4x² -17x + 60 at x = 5
|
||||
# polynomial_eval([1, -4, -17, 60], x=5) --> 0
|
||||
# polynomial_eval([1, -4, -17, 60], x=5) → 0
|
||||
n = len(coefficients)
|
||||
if not n:
|
||||
return type(x)(0)
|
||||
|
@ -1061,14 +1064,14 @@ The following recipes have a more mathematical flavor:
|
|||
f(x) = x³ -4x² -17x + 60
|
||||
f'(x) = 3x² -8x -17
|
||||
"""
|
||||
# polynomial_derivative([1, -4, -17, 60]) --> [3, -8, -17]
|
||||
# polynomial_derivative([1, -4, -17, 60]) → [3, -8, -17]
|
||||
n = len(coefficients)
|
||||
powers = reversed(range(1, n))
|
||||
return list(map(operator.mul, coefficients, powers))
|
||||
|
||||
def sieve(n):
|
||||
"Primes less than n."
|
||||
# sieve(30) --> 2 3 5 7 11 13 17 19 23 29
|
||||
# sieve(30) → 2 3 5 7 11 13 17 19 23 29
|
||||
if n > 2:
|
||||
yield 2
|
||||
start = 3
|
||||
|
@ -1082,9 +1085,9 @@ The following recipes have a more mathematical flavor:
|
|||
|
||||
def factor(n):
|
||||
"Prime factors of n."
|
||||
# factor(99) --> 3 3 11
|
||||
# factor(1_000_000_000_000_007) --> 47 59 360620266859
|
||||
# factor(1_000_000_000_000_403) --> 1000000000000403
|
||||
# factor(99) → 3 3 11
|
||||
# factor(1_000_000_000_000_007) → 47 59 360620266859
|
||||
# factor(1_000_000_000_000_403) → 1000000000000403
|
||||
for prime in sieve(math.isqrt(n) + 1):
|
||||
while not n % prime:
|
||||
yield prime
|
||||
|
@ -1097,7 +1100,7 @@ The following recipes have a more mathematical flavor:
|
|||
def totient(n):
|
||||
"Count of natural numbers up to n that are coprime to n."
|
||||
# https://mathworld.wolfram.com/TotientFunction.html
|
||||
# totient(12) --> 4 because len([1, 5, 7, 11]) == 4
|
||||
# totient(12) → 4 because len([1, 5, 7, 11]) == 4
|
||||
for p in unique_justseen(factor(n)):
|
||||
n -= n // p
|
||||
return n
|
||||
|
@ -1567,6 +1570,13 @@ The following recipes have a more mathematical flavor:
|
|||
>>> ranges = [range(5, 1000), range(4, 3000), range(0), range(3, 2000), range(2, 5000), range(1, 3500)]
|
||||
>>> collections.Counter(roundrobin(ranges)) == collections.Counter(ranges)
|
||||
True
|
||||
>>> # Verify that the inputs are consumed lazily
|
||||
>>> input_iterators = list(map(iter, ['abcd', 'ef', '', 'ghijk', 'l', 'mnopqr']))
|
||||
>>> output_iterator = roundrobin(*input_iterators)
|
||||
>>> ''.join(islice(output_iterator, 10))
|
||||
'aeglmbfhnc'
|
||||
>>> ''.join(chain(*input_iterators))
|
||||
'dijkopqr'
|
||||
|
||||
>>> def is_odd(x):
|
||||
... return x % 2 == 1
|
||||
|
@ -1676,7 +1686,7 @@ The following recipes have a more mathematical flavor:
|
|||
|
||||
def triplewise(iterable):
|
||||
"Return overlapping triplets from an iterable"
|
||||
# triplewise('ABCDEFG') --> ABC BCD CDE DEF EFG
|
||||
# triplewise('ABCDEFG') → ABC BCD CDE DEF EFG
|
||||
for (a, _), (b, c) in pairwise(pairwise(iterable)):
|
||||
yield a, b, c
|
||||
|
||||
|
|
Loading…
Reference in New Issue