Better presentation order for recipes. (gh-116755)
This commit is contained in:
parent
e54bdeab9c
commit
5ff012a449
@ -785,8 +785,8 @@ well as with the built-in itertools such as ``map()``, ``filter()``,
|
|||||||
|
|
||||||
A secondary purpose of the recipes is to serve as an incubator. The
|
A secondary purpose of the recipes is to serve as an incubator. The
|
||||||
``accumulate()``, ``compress()``, and ``pairwise()`` itertools started out as
|
``accumulate()``, ``compress()``, and ``pairwise()`` itertools started out as
|
||||||
recipes. Currently, the ``sliding_window()`` and ``iter_index()`` recipes
|
recipes. Currently, the ``sliding_window()``, ``iter_index()``, and ``sieve()``
|
||||||
are being tested to see whether they prove their worth.
|
recipes are being tested to see whether they prove their worth.
|
||||||
|
|
||||||
Substantially all of these recipes and many, many others can be installed from
|
Substantially all of these recipes and many, many others can be installed from
|
||||||
the `more-itertools project <https://pypi.org/project/more-itertools/>`_ found
|
the `more-itertools project <https://pypi.org/project/more-itertools/>`_ found
|
||||||
@ -795,12 +795,12 @@ on the Python Package Index::
|
|||||||
python -m pip install more-itertools
|
python -m pip install more-itertools
|
||||||
|
|
||||||
Many of the recipes offer the same high performance as the underlying toolset.
|
Many of the recipes offer the same high performance as the underlying toolset.
|
||||||
Superior memory performance is kept by processing elements one at a time
|
Superior memory performance is kept by processing elements one at a time rather
|
||||||
rather than bringing the whole iterable into memory all at once. Code volume is
|
than bringing the whole iterable into memory all at once. Code volume is kept
|
||||||
kept small by linking the tools together in a functional style which helps
|
small by linking the tools together in a `functional style
|
||||||
eliminate temporary variables. High speed is retained by preferring
|
<https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf>`_. High speed
|
||||||
"vectorized" building blocks over the use of for-loops and :term:`generator`\s
|
is retained by preferring "vectorized" building blocks over the use of for-loops
|
||||||
which incur interpreter overhead.
|
and :term:`generators <generator>` which incur interpreter overhead.
|
||||||
|
|
||||||
.. testcode::
|
.. testcode::
|
||||||
|
|
||||||
@ -873,6 +873,14 @@ which incur interpreter overhead.
|
|||||||
"Returns True if all the elements are equal to each other."
|
"Returns True if all the elements are equal to each other."
|
||||||
return len(take(2, groupby(iterable, key))) <= 1
|
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
|
||||||
|
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):
|
def unique_everseen(iterable, key=None):
|
||||||
"List unique elements, preserving order. Remember all elements ever seen."
|
"List unique elements, preserving order. Remember all elements ever seen."
|
||||||
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
|
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
|
||||||
@ -889,35 +897,6 @@ which incur interpreter overhead.
|
|||||||
seen.add(k)
|
seen.add(k)
|
||||||
yield element
|
yield element
|
||||||
|
|
||||||
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
|
|
||||||
if key is None:
|
|
||||||
return map(operator.itemgetter(0), groupby(iterable))
|
|
||||||
return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
|
|
||||||
|
|
||||||
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
|
|
||||||
seq_index = getattr(iterable, 'index', None)
|
|
||||||
if seq_index is None:
|
|
||||||
# Path for general iterables
|
|
||||||
it = islice(iterable, start, stop)
|
|
||||||
for i, element in enumerate(it, start):
|
|
||||||
if element is value or element == value:
|
|
||||||
yield i
|
|
||||||
else:
|
|
||||||
# Path for sequences with an index() method
|
|
||||||
stop = len(iterable) if stop is None else stop
|
|
||||||
i = start
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
yield (i := seq_index(value, i, stop))
|
|
||||||
i += 1
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def sliding_window(iterable, n):
|
def sliding_window(iterable, n):
|
||||||
"Collect data into overlapping fixed-length chunks or blocks."
|
"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
|
||||||
@ -967,6 +946,27 @@ which incur interpreter overhead.
|
|||||||
slices = starmap(slice, combinations(range(len(seq) + 1), 2))
|
slices = starmap(slice, combinations(range(len(seq) + 1), 2))
|
||||||
return map(operator.getitem, repeat(seq), slices)
|
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
|
||||||
|
seq_index = getattr(iterable, 'index', None)
|
||||||
|
if seq_index is None:
|
||||||
|
# Path for general iterables
|
||||||
|
it = islice(iterable, start, stop)
|
||||||
|
for i, element in enumerate(it, start):
|
||||||
|
if element is value or element == value:
|
||||||
|
yield i
|
||||||
|
else:
|
||||||
|
# Path for sequences with an index() method
|
||||||
|
stop = len(iterable) if stop is None else stop
|
||||||
|
i = start
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
yield (i := seq_index(value, i, stop))
|
||||||
|
i += 1
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
def iter_except(func, exception, first=None):
|
def iter_except(func, exception, first=None):
|
||||||
""" Call a function repeatedly until an exception is raised.
|
""" Call a function repeatedly until an exception is raised.
|
||||||
|
|
||||||
@ -1047,8 +1047,8 @@ The following recipes have a more mathematical flavor:
|
|||||||
|
|
||||||
Computes with better numeric stability than Horner's method.
|
Computes with better numeric stability than Horner's method.
|
||||||
"""
|
"""
|
||||||
# Evaluate x³ -4x² -17x + 60 at x = 2.5
|
# Evaluate x³ -4x² -17x + 60 at x = 5
|
||||||
# polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
|
# polynomial_eval([1, -4, -17, 60], x=5) --> 0
|
||||||
n = len(coefficients)
|
n = len(coefficients)
|
||||||
if not n:
|
if not n:
|
||||||
return type(x)(0)
|
return type(x)(0)
|
||||||
@ -1311,10 +1311,10 @@ The following recipes have a more mathematical flavor:
|
|||||||
|
|
||||||
>>> from fractions import Fraction
|
>>> from fractions import Fraction
|
||||||
>>> from decimal import Decimal
|
>>> from decimal import Decimal
|
||||||
>>> polynomial_eval([1, -4, -17, 60], x=2)
|
>>> polynomial_eval([1, -4, -17, 60], x=5)
|
||||||
18
|
0
|
||||||
>>> x = 2; x**3 - 4*x**2 -17*x + 60
|
>>> x = 5; x**3 - 4*x**2 -17*x + 60
|
||||||
18
|
0
|
||||||
>>> polynomial_eval([1, -4, -17, 60], x=2.5)
|
>>> polynomial_eval([1, -4, -17, 60], x=2.5)
|
||||||
8.125
|
8.125
|
||||||
>>> x = 2.5; x**3 - 4*x**2 -17*x + 60
|
>>> x = 2.5; x**3 - 4*x**2 -17*x + 60
|
||||||
|
Loading…
x
Reference in New Issue
Block a user