Improved avg query

This commit is contained in:
Sven Heidemann 2021-07-27 12:35:14 +02:00
parent d4b5c32a21
commit daac14e099
6 changed files with 50 additions and 37 deletions

View File

@ -20,8 +20,8 @@ from cpl_query.extension.iterable_abc import IterableABC
class Iterable(IterableABC): class Iterable(IterableABC):
def __init__(self): def __init__(self, t: type = None, values: list = None):
IterableABC.__init__(self) IterableABC.__init__(self, t, values)
def any(self, func: Callable) -> bool: def any(self, func: Callable) -> bool:
return any_query(self, func) return any_query(self, func)
@ -29,8 +29,8 @@ class Iterable(IterableABC):
def all(self, func: Callable) -> bool: def all(self, func: Callable) -> bool:
return all_query(self, func) return all_query(self, func)
def average(self, t: type, func: Callable) -> Union[int, float, complex]: def average(self, func: Callable = None) -> Union[int, float, complex]:
return avg_query(self, t, func) return avg_query(self, func)
def contains(self, value: object) -> bool: def contains(self, value: object) -> bool:
return contains_query(self, value) return contains_query(self, value)

2
src/cpl_query/_helper.py Normal file
View File

@ -0,0 +1,2 @@
def is_number(t: type) -> bool:
return issubclass(t, int) or issubclass(t, float) or issubclass(t, complex)

View File

@ -1,28 +1,27 @@
from typing import Callable, Union from typing import Callable, Union
from cpl_query._helper import is_number
from cpl_query.exceptions import InvalidTypeException, WrongTypeException, ExceptionArgument, ArgumentNoneException from cpl_query.exceptions import InvalidTypeException, WrongTypeException, ExceptionArgument, ArgumentNoneException
from cpl_query.extension.iterable_abc import IterableABC from cpl_query.extension.iterable_abc import IterableABC
def avg_query(_list: IterableABC, _t: type, _func: Callable) -> Union[int, float, complex]: def avg_query(_list: IterableABC, _func: Callable) -> Union[int, float, complex]:
average = 0
count = len(_list)
if _list is None: if _list is None:
raise ArgumentNoneException(ExceptionArgument.list) raise ArgumentNoneException(ExceptionArgument.list)
if _func is None: average = 0
raise ArgumentNoneException(ExceptionArgument.func) count = len(_list)
if _t != int and _t != float and _t != complex:
raise InvalidTypeException()
for element in _list: for element in _list:
value = _func(element) if _func is not None:
if type(value) != _t: value = _func(element)
else:
value = element
if _list.type is not None and type(element) != _list.type or not is_number(type(value)):
raise WrongTypeException() raise WrongTypeException()
average += value average += value
return average / count return average / count

View File

@ -5,17 +5,35 @@ from typing import Optional, Callable, Union
class IterableABC(ABC, list): class IterableABC(ABC, list):
@abstractmethod @abstractmethod
def __init__(self): def __init__(self, t: type = None, values: list = None):
list.__init__(self) list.__init__(self)
if t == any:
t = None
self._type = t
if values is not None:
for value in values:
self.append(value)
@property
def type(self) -> type:
return self._type
@abstractmethod @abstractmethod
def any(self, func: Callable) -> bool: pass def any(self, func: Callable) -> bool: pass
@abstractmethod @abstractmethod
def all(self, func: Callable) -> bool: pass def all(self, func: Callable) -> bool: pass
def append(self, __object: object) -> None:
if self._type is not None and type(__object) != self._type and not isinstance(type(__object), self._type):
raise Exception(f'Unexpected type: {type(__object)}')
super().append(__object)
@abstractmethod @abstractmethod
def average(self, t: type, func: Callable) -> Union[int, float, complex]: pass def average(self, func: Callable = None) -> Union[int, float, complex]: pass
@abstractmethod @abstractmethod
def contains(self, value: object) -> bool: pass def contains(self, value: object) -> bool: pass

View File

@ -4,15 +4,4 @@ from .._extension.iterable import Iterable
class List(Iterable): class List(Iterable):
def __init__(self, t: type = None, values: list = None): def __init__(self, t: type = None, values: list = None):
Iterable.__init__(self) Iterable.__init__(self, t, values)
self._type = t
if values is not None:
self.extend(values)
def append(self, __object: object) -> None:
if self._type is not None and type(__object) != self._type and not isinstance(type(__object), self._type):
raise Exception(f'Unexpected type: {type(__object)}')
super().append(__object)

View File

@ -66,19 +66,24 @@ class QueryTest(unittest.TestCase):
avg += user.address.nr avg += user.address.nr
avg = avg / len(self._tests) avg = avg / len(self._tests)
res = self._tests.average(int, lambda u: u.address.nr) res = self._tests.average(lambda u: u.address.nr)
self.assertEqual(res, avg) self.assertEqual(avg, res)
def invalid():
e_res = self._tests.average(str, lambda u: u.address.nr)
def wrong(): def wrong():
e_res = self._tests.average(int, lambda u: u.address.street) e_res = self._tests.average(lambda u: u.address.street)
self.assertRaises(InvalidTypeException, invalid)
self.assertRaises(WrongTypeException, wrong) self.assertRaises(WrongTypeException, wrong)
tests = List(int, list(range(0, 100)))
self.assertEqual(sum(tests) / len(tests), tests.average())
def wrong2():
tests2 = List(int, values=list(range(0, 100)))
e_res = tests2.average(lambda u: u.address.nr)
self.assertRaises(AttributeError, wrong2)
def test_contains(self): def test_contains(self):
self.assertTrue(self._tests.contains(self._t_user)) self.assertTrue(self._tests.contains(self._t_user))
self.assertFalse(self._tests.contains(User("Test", None))) self.assertFalse(self._tests.contains(User("Test", None)))