My proposal for a one-liner
{key(elt): elt for elt in reversed(iterable)}.values()
The order of the iterable is not kept because of the reversed
call, but without it the later duplicate elements would override the earliest ones. Might need to be adjusted depending on your constraints.
Can be used like so, with the example given in the question:
from typing import Iterable, Callable, TypeVar
from operator import itemgetter
T = TypeVar("T")
def get_unique_elements(iterable: Iterable[T], key: Callable[[T], any]) -> Iterable[T]:
"""
Returns all unique elements from an iterable,
using the key function to establish unicity.
Elements appearing first will have priority in case of duplicates
"""
return {key(elt): elt for elt in reversed(iterable)}.values()
list(get_unique_elements(
[
["element1", 12],
["element2", 2],
["element3", 12],
["element4", 36],
["element5", 12],
],
key=itemgetter(1),
)
Out: [['element1', 12], ['element4', 36], ['element2', 2]]