You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
36 lines
884 B
36 lines
884 B
3 years ago
|
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
|