| from itertools import filterfalse |
| |
| from typing import ( |
| Callable, |
| Iterable, |
| Iterator, |
| Optional, |
| Set, |
| TypeVar, |
| Union, |
| ) |
| |
| # Type and type variable definitions |
| _T = TypeVar('_T') |
| _U = TypeVar('_U') |
| |
| |
| def unique_everseen( |
| iterable: Iterable[_T], key: Optional[Callable[[_T], _U]] = None |
| ) -> Iterator[_T]: |
| "List unique elements, preserving order. Remember all elements ever seen." |
| # unique_everseen('AAAABBBCCDAABBB') --> A B C D |
| # unique_everseen('ABBCcAD', str.lower) --> A B C D |
| seen: Set[Union[_T, _U]] = set() |
| seen_add = seen.add |
| if key is None: |
| for element in filterfalse(seen.__contains__, iterable): |
| seen_add(element) |
| yield element |
| else: |
| for element in iterable: |
| k = key(element) |
| if k not in seen: |
| seen_add(k) |
| yield element |