Skip to content

Commit

Permalink
Merge pull request #851 from more-itertools/version-10.3.0
Browse files Browse the repository at this point in the history
Changes for version 10.3.0
  • Loading branch information
bbayles committed Jun 10, 2024
2 parents 6944752 + 94e4f88 commit 7e46c39
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 22 deletions.
27 changes: 17 additions & 10 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ Python iterables.
| | `zip_offset <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.zip_offset>`_, |
| | `zip_equal <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.zip_equal>`_, |
| | `zip_broadcast <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.zip_broadcast>`_, |
| | `dotproduct <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.dotproduct>`_, |
| | `convolve <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.convolve>`_, |
| | `flatten <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.flatten>`_, |
| | `roundrobin <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.roundrobin>`_, |
| | `prepend <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.prepend>`_, |
Expand All @@ -77,6 +75,7 @@ Python iterables.
| | `consecutive_groups <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.consecutive_groups>`_, |
| | `run_length <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.run_length>`_, |
| | `map_reduce <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.map_reduce>`_, |
| | `join_mappings <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.join_mappings>`_, |
| | `exactly_n <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.exactly_n>`_, |
| | `is_sorted <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.is_sorted>`_, |
| | `all_equal <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.all_equal>`_, |
Expand Down Expand Up @@ -107,12 +106,26 @@ Python iterables.
| | `tail <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.tail>`_, |
| | `unique_everseen <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.unique_everseen>`_, |
| | `unique_justseen <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.unique_justseen>`_, |
| | `unique <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.unique>`_, |
| | `duplicates_everseen <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.duplicates_everseen>`_, |
| | `duplicates_justseen <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.duplicates_justseen>`_, |
| | `classify_unique <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.classify_unique>`_, |
| | `longest_common_prefix <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.longest_common_prefix>`_, |
| | `takewhile_inclusive <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.takewhile_inclusive>`_ |
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Math | `dft <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.dft>`_, |
| | `idft <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.idft>`_, |
| | `convolve <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.convolve>`_, |
| | `dotproduct <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.dotproduct>`_, |
| | `factor <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.factor>`_, |
| | `matmul <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.matmul>`_, |
| | `polynomial_from_roots <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.polynomial_from_roots>`_, |
| | `polynomial_derivative <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.polynomial_derivative>`_, |
| | `polynomial_eval <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.polynomial_eval>`_, |
| | `sieve <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sieve>`_, |
| | `sum_of_squares <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sum_of_squares>`_, |
| | `totient <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.totient>`_ |
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Combinatorics | `distinct_permutations <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.distinct_permutations>`_, |
| | `distinct_combinations <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.distinct_combinations>`_, |
| | `circular_shifts <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.circular_shifts>`_, |
Expand All @@ -125,6 +138,7 @@ Python iterables.
| | `gray_product <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.gray_product>`_, |
| | `outer_product <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.outer_product>`_, |
| | `powerset <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.powerset>`_, |
| | `powerset_of_sets <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.powerset_of_sets>`_, |
| | `random_product <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.random_product>`_, |
| | `random_permutation <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.random_permutation>`_, |
| | `random_combination <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.random_combination>`_, |
Expand Down Expand Up @@ -156,15 +170,8 @@ Python iterables.
| | `consume <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.consume>`_, |
| | `tabulate <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.tabulate>`_, |
| | `repeatfunc <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.repeatfunc>`_, |
| | `polynomial_from_roots <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.polynomial_from_roots>`_, |
| | `polynomial_eval <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.polynomial_eval>`_, |
| | `polynomial_derivative <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.polynomial_derivative>`_, |
| | `sieve <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sieve>`_, |
| | `factor <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.factor>`_, |
| | `matmul <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.matmul>`_, |
| | `sum_of_squares <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.sum_of_squares>`_, |
| | `totient <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.totient>`_, |
| | `reshape <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.reshape>`_ |
| | `doublestarmap <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.doublestarmap>`_ |
+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+


Expand Down
1 change: 1 addition & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ These tools yield certain items from an iterable.
.. autofunction:: tail
.. autofunction:: unique_everseen
.. autofunction:: unique_justseen
.. autofunction:: unique


Combinatorics
Expand Down
21 changes: 21 additions & 0 deletions docs/versions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ Version History
.. automodule:: more_itertools
:noindex:

10.3.0
------

* New functions
* :func:`powerset_of_sets`, :func:`dft`, and :func:`idft` (thanks to rhettinger)
* :func:`join_mappings` (thanks to NeilGirdhar and rhettinger)
* :func:`doublestarmap` (thanks to Skeen, monk-time, DamianB-BitFlipper, and ergoithz)
* :func:`unique` (thanks to rhettinger)

* Changes to existing functions
* :func:`collapse`, :func:`chunked_even`, :func:`ichunked`, :func:`padded`, and :func:`windowed` were optimized and improved (thanks to james-wasson)
* :func:`totient` was optimized (thanks to rhettinger)
* :func:`roundrobin` was updated and improved (thanks to rhettinger)
* :func:`all_equal` now accepts a *key* parameter.
* The docs for :func:`value_chain` were improved (thanks to bjrtx)
* The type annotations for :class:`countable` were improved (thanks to aidanholm)

* Other changes
* Unit tests were improved (thanks to haukex)
* Some documentation issues were fixed (thanks to bjrtx and DimitriPapadopoulos)

10.2.0
------

Expand Down
2 changes: 1 addition & 1 deletion more_itertools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
from .more import * # noqa
from .recipes import * # noqa

__version__ = '10.2.0'
__version__ = '10.3.0'
20 changes: 20 additions & 0 deletions more_itertools/recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
'totient',
'transpose',
'triplewise',
'unique',
'unique_everseen',
'unique_justseen',
]
Expand Down Expand Up @@ -534,6 +535,25 @@ def unique_justseen(iterable, key=None):
return map(next, map(operator.itemgetter(1), groupby(iterable, key)))


def unique(iterable, key=None, reverse=False):
"""Yields unique elements in sorted order.
>>> list(unique([[1, 2], [3, 4], [1, 2]]))
[[1, 2], [3, 4]]
*key* and *reverse* are passed to :func:`sorted`.
>>> list(unique('ABBcCAD', str.casefold))
['A', 'B', 'c', 'D']
>>> list(unique('ABBcCAD', str.casefold, reverse=True))
['D', 'c', 'B', 'A']
The elements in *iterable* need not be hashable, but they must be
comparable for sorting to work.
"""
return unique_justseen(sorted(iterable, key=key, reverse=reverse), key=key)


def iter_except(func, exception, first=None):
"""Yields results from a function repeatedly until an exception is raised.
Expand Down
5 changes: 5 additions & 0 deletions more_itertools/recipes.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ def unique_everseen(
def unique_justseen(
iterable: Iterable[_T], key: Callable[[_T], object] | None = ...
) -> Iterator[_T]: ...
def unique(
iterable: Iterable[_T],
key: Callable[[_T], object] | None = ...,
reverse: bool = False,
) -> Iterator[_T]: ...
@overload
def iter_except(
func: Callable[[], _T],
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 10.2.0
current_version = 10.3.0
commit = True
tag = False
files = more_itertools/__init__.py
Expand Down
30 changes: 20 additions & 10 deletions tests/test_recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,45 +395,55 @@ def test_combinatorics(self):


class UniqueEverseenTests(TestCase):
"""Tests for ``unique_everseen()``"""

def test_everseen(self):
"""ensure duplicate elements are ignored"""
u = mi.unique_everseen('AAAABBBBCCDAABBB')
self.assertEqual(['A', 'B', 'C', 'D'], list(u))

def test_custom_key(self):
"""ensure the custom key comparison works"""
u = mi.unique_everseen('aAbACCc', key=str.lower)
self.assertEqual(list('abC'), list(u))

def test_unhashable(self):
"""ensure things work for unhashable items"""
iterable = ['a', [1, 2, 3], [1, 2, 3], 'a']
u = mi.unique_everseen(iterable)
self.assertEqual(list(u), ['a', [1, 2, 3]])

def test_unhashable_key(self):
"""ensure things work for unhashable items with a custom key"""
iterable = ['a', [1, 2, 3], [1, 2, 3], 'a']
u = mi.unique_everseen(iterable, key=lambda x: x)
self.assertEqual(list(u), ['a', [1, 2, 3]])


class UniqueJustseenTests(TestCase):
"""Tests for ``unique_justseen()``"""

def test_justseen(self):
"""ensure only last item is remembered"""
u = mi.unique_justseen('AAAABBBCCDABB')
self.assertEqual(list('ABCDAB'), list(u))

def test_custom_key(self):
"""ensure the custom key comparison works"""
u = mi.unique_justseen('AABCcAD', str.lower)
self.assertEqual(list('ABCAD'), list(u))


class UniqueTests(TestCase):
def test_basic(self):
iterable = [0, 1, 1, 8, 9, 9, 9, 8, 8, 1, 9, 9]
actual = list(mi.unique(iterable))
expected = [0, 1, 8, 9]
self.assertEqual(actual, expected)

def test_key(self):
iterable = ['1', '1', '10', '10', '2', '2', '20', '20']
actual = list(mi.unique(iterable, key=int))
expected = ['1', '2', '10', '20']
self.assertEqual(actual, expected)

def test_reverse(self):
iterable = ['1', '1', '10', '10', '2', '2', '20', '20']
actual = list(mi.unique(iterable, key=int, reverse=True))
expected = ['20', '10', '2', '1']
self.assertEqual(actual, expected)


class IterExceptTests(TestCase):
"""Tests for ``iter_except()``"""

Expand Down

0 comments on commit 7e46c39

Please sign in to comment.