From 669133d4919cfc4f16c3187006baa5332728294c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:20:35 +0200 Subject: [PATCH] Added distinct query --- src/cpl_query/_extension/iterable.py | 6 ++++++ src/cpl_query/_query/distinct_query.py | 24 ++++++++++++++++++++++++ src/cpl_query/extension/iterable_abc.py | 9 ++++++--- src/cpl_query/tests/query_test.py | 4 ++++ 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 src/cpl_query/_query/distinct_query.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index f925851e..60f1b94d 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -7,6 +7,7 @@ from .._query.any_query import any_query from .._query.avg_query import avg_query from .._query.contains_query import contains_query from .._query.count_query import count_query +from .._query.distinct_query import distinct_query from .._query.first_query import first_or_default_query, first_query from .._query.for_each_query import for_each_query from .._query.order_by import order_by_query, order_by_descending_query @@ -35,6 +36,11 @@ class Iterable(IterableABC): def count(self, func: Callable = None) -> int: return count_query(self, func) + def distinct(self, func: Callable) -> IterableABC: + res = distinct_query(self, func) + res.__class__ = Iterable + return res + def first(self) -> any: return first_query(self) diff --git a/src/cpl_query/_query/distinct_query.py b/src/cpl_query/_query/distinct_query.py new file mode 100644 index 00000000..791ef7c7 --- /dev/null +++ b/src/cpl_query/_query/distinct_query.py @@ -0,0 +1,24 @@ +from collections import Callable + +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument +from cpl_query.extension.iterable_abc import IterableABC + + +def distinct_query(_list: IterableABC, _func: Callable) -> IterableABC: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + + result = IterableABC() + known_values = [] + for element in _list: + value = _func(element) + if value in known_values: + continue + + known_values.append(value) + result.append(element) + + return result diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index 6a85d604..bd031833 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -23,6 +23,9 @@ class IterableABC(ABC, list): @abstractmethod def count(self, func: Callable) -> int: pass + @abstractmethod + def distinct(self, func: Callable) -> 'IterableABC': pass + @abstractmethod def first(self) -> any: pass @@ -33,13 +36,13 @@ class IterableABC(ABC, list): def for_each(self, func: Callable): pass @abstractmethod - def order_by(self, func: Callable): pass + def order_by(self, func: Callable) -> 'IterableABC': pass @abstractmethod - def order_by_descending(self, func: Callable): pass + def order_by_descending(self, func: Callable) -> 'IterableABC': pass @abstractmethod - def single(self): pass + def single(self) -> any: pass @abstractmethod def single_or_default(self) -> Optional[any]: pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index cb7a42a4..9a187f3e 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -87,6 +87,10 @@ class QueryTest(unittest.TestCase): self.assertEqual(len(self._tests), self._tests.count()) self.assertEqual(1, self._tests.count(lambda u: u == self._t_user)) + def test_distinct(self): + res = self._tests.distinct(lambda u: u.address.nr).where(lambda u: u.address.nr == 5) + self.assertEqual(1, len(res)) + def test_first(self): results = [] for user in self._tests: