diff --git a/audeer/__init__.py b/audeer/__init__.py index f56d381..f35709b 100644 --- a/audeer/__init__.py +++ b/audeer/__init__.py @@ -34,6 +34,7 @@ from audeer.core.utils import sort_versions from audeer.core.utils import to_list from audeer.core.utils import uid +from audeer.core.utils import unique from audeer.core.version import LooseVersion from audeer.core.version import StrictVersion diff --git a/audeer/core/utils.py b/audeer/core/utils.py index e4cabb4..aea33fd 100644 --- a/audeer/core/utils.py +++ b/audeer/core/utils.py @@ -829,3 +829,28 @@ def uid( uid = uid[-8:] return uid + + +def unique(sequence: typing.Iterable) -> typing.List: + r"""Unique values in its original order. + + This is an alternative to ``list(set(x))``, + which does not preserve the original order. + + Args: + sequence: sequence of values + + Returns: + unique values from ``x`` in order of appearance + + Examples: + >>> list(set([2, 2, 1])) + [1, 2] + >>> unique([2, 2, 1]) + [2, 1] + + """ + # https://stackoverflow.com/a/480227 + seen = set() + seen_add = seen.add + return [x for x in sequence if not (x in seen or seen_add(x))] diff --git a/docs/api-src/audeer.rst b/docs/api-src/audeer.rst index 6171999..aa780a2 100644 --- a/docs/api-src/audeer.rst +++ b/docs/api-src/audeer.rst @@ -44,3 +44,4 @@ audeer to_list touch uid + unique diff --git a/tests/test_utils.py b/tests/test_utils.py index c1f3b8e..25fe37c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -531,3 +531,29 @@ def test_uid(from_string, short): assert uid == uid2 else: assert uid != uid2 + + +@pytest.mark.parametrize( + "sequence, expected", + [ + ([], []), + ([1], [1]), + ([2, 1], [2, 1]), + ([2, 1, 2], [2, 1]), + (["a", 1, "a", 1], ["a", 1]), + ((1, 1), [1]), + ("dddnnfhg", ["d", "n", "f", "h", "g"]), + ([None, None], [None]), + ], +) +def test_unique(sequence, expected): + r"""Test audeer.unique(). + + Should return unique values in original order. + + Args: + sequence: sequence if input values + expected: expected unique list + + """ + assert audeer.unique(sequence) == expected