From d4b5c32a2112bb248720706d2295008bd2d68585 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 27 Jul 2021 11:57:42 +0200 Subject: [PATCH] Added min and max queries --- src/cpl_query/_extension/iterable.py | 7 ++++ src/cpl_query/_query/max_min.py | 48 +++++++++++++++++++++++++ src/cpl_query/extension/iterable_abc.py | 5 ++- src/cpl_query/tests/query_test.py | 10 +++++- 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/cpl_query/_query/max_min.py diff --git a/src/cpl_query/_extension/iterable.py b/src/cpl_query/_extension/iterable.py index 45180a9c..15037603 100644 --- a/src/cpl_query/_extension/iterable.py +++ b/src/cpl_query/_extension/iterable.py @@ -11,6 +11,7 @@ from .._query.distinct import distinct_query from .._query.element_at import element_at_query, element_at_or_default_query from .._query.first_last import first_or_default_query, first_query, last_or_default_query, last_query from .._query.for_each import for_each_query +from .._query.max_min import max_query, min_query from .._query.order_by import order_by_query, order_by_descending_query from .._query.single import single_query, single_or_default_query from .._query.where import where_query @@ -63,6 +64,12 @@ class Iterable(IterableABC): def for_each(self, func: Callable): for_each_query(self, func) + def max(self, t: type, func: Callable) -> Union[int, float, complex]: + return max_query(self, t, func) + + def min(self, t: type, func: Callable) -> Union[int, float, complex]: + return min_query(self, t, func) + def order_by(self, func: Callable) -> OrderedIterableABC: res = order_by_query(self, func) res.__class__ = OrderedIterable diff --git a/src/cpl_query/_query/max_min.py b/src/cpl_query/_query/max_min.py new file mode 100644 index 00000000..82dc01c0 --- /dev/null +++ b/src/cpl_query/_query/max_min.py @@ -0,0 +1,48 @@ +from collections import Callable +from typing import Union + +from cpl_query.exceptions import ArgumentNoneException, ExceptionArgument, InvalidTypeException +from cpl_query.extension.iterable_abc import IterableABC + + +def max_query(_list: IterableABC, _t: type, _func: Callable) -> Union[int, float, complex]: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + + if _t != int and _t != float and _t != complex: + raise InvalidTypeException() + + max_value = _t() + for element in _list: + value = _func(element) + if value > max_value: + max_value = value + + return max_value + + +def min_query(_list: IterableABC, _t: type, _func: Callable) -> Union[int, float, complex]: + if _list is None: + raise ArgumentNoneException(ExceptionArgument.list) + + if _func is None: + raise ArgumentNoneException(ExceptionArgument.func) + + if _t != int and _t != float and _t != complex: + raise InvalidTypeException() + + min_value = _t() + is_first = True + for element in _list: + value = _func(element) + if is_first: + min_value = value + is_first = False + + if value < min_value: + min_value = value + + return min_value diff --git a/src/cpl_query/extension/iterable_abc.py b/src/cpl_query/extension/iterable_abc.py index c9d0105b..6a94c8c3 100644 --- a/src/cpl_query/extension/iterable_abc.py +++ b/src/cpl_query/extension/iterable_abc.py @@ -45,7 +45,10 @@ class IterableABC(ABC, list): def first_or_default(self) -> any: pass @abstractmethod - def for_each(self, func: Callable): pass + def for_each(self, func: Callable) -> Union[int, float, complex]: pass + + @abstractmethod + def max(self, t: type, func: Callable) -> Union[int, float, complex]: pass @abstractmethod def order_by(self, func: Callable) -> 'IterableABC': pass diff --git a/src/cpl_query/tests/query_test.py b/src/cpl_query/tests/query_test.py index 64f5f23c..c5522813 100644 --- a/src/cpl_query/tests/query_test.py +++ b/src/cpl_query/tests/query_test.py @@ -28,7 +28,7 @@ class QueryTest(unittest.TestCase): String.random_string(string.ascii_letters, 8).lower(), Address( String.random_string(string.ascii_letters, 10).lower(), - randint(0, 10) + randint(1, 10) ) ) @@ -162,6 +162,14 @@ class QueryTest(unittest.TestCase): self.assertEqual(len(users), len(self._tests)) + def test_max(self): + res = self._tests.max(int, lambda u: u.address.nr) + self.assertEqual(self._t_user.address.nr, res) + + def test_min(self): + res = self._tests.min(int, lambda u: u.address.nr) + self.assertEqual(1, res) + def test_order_by(self): res = self._tests.order_by(lambda user: user.address.street) res2 = self._tests.order_by(lambda user: user.address.nr)