Source code for tests.group_by.test_group_by

"""
*shmakovpn_tools/shmakovpn/tests/group_by/test_group_by.py*

Python groupby examnples.

Author: shmakovpn <shmakovpn@yandex.ru>

Date: 2020-09-30

"""
import unittest
from operator import add
from itertools import groupby
from functools import reduce
# type hints
from typing import List, Dict, Any


[docs]class TestGroupBy(unittest.TestCase): """ This class contains tests of different variants of **groupby** """ data2: List[Dict[str, Any]] = [ {'name': 'alex', 'score': 2, }, {'name': 'john', 'score': 4, }, {'name': 'dan', 'score': 1, }, {'name': 'alex', 'score': 6, }, {'name': 'dan', 'score': 3, }, ] """ the dataset for tests"""
[docs] def test_sorted(self) -> None: """ Tests builtin function **sorted** """ self.assertEqual( sorted(self.data2, key=lambda row: row['name']), # sorted data2 by name [ {'name': 'alex', 'score': 2}, {'name': 'alex', 'score': 6}, {'name': 'dan', 'score': 1}, {'name': 'dan', 'score': 3}, {'name': 'john', 'score': 4}, ] )
[docs] def test_group_by_itertools_sorted(self) -> None: """ Tests **itertools.groupby** on sorted dataset. This test figures out that **itertools.groupby** really works on the sorted dataset """ keys = [] groups = [] for key, group in groupby( sorted(self.data2, key=lambda row: row['name']), key=lambda row: row['name'], ): keys.append(key) groups.append(list(group)) self.assertEqual( keys, ['alex', 'dan', 'john'] ) self.assertEqual( groups, [ [ {'name': 'alex', 'score': 2}, {'name': 'alex', 'score': 6}, ], [ {'name': 'dan', 'score': 1}, {'name': 'dan', 'score': 3}, ], [ {'name': 'john', 'score': 4}, ] ] )
[docs] def test_group_by_itertools_unsorted(self) -> None: """ Tests **itertools.groupby** on unsorted dataset. This test figures out that **itertools.groupby** doesn't work on the sorted dataset """ keys = [] groups = [] for key, group in groupby( self.data2, key=lambda row: row['name'], ): keys.append(key) groups.append(list(group)) self.assertEqual( keys, ['alex', 'john', 'dan', 'alex', 'dan'] ) self.assertEqual( groups, [ [{'name': 'alex', 'score': 2, }, ], [{'name': 'john', 'score': 4, }, ], [{'name': 'dan', 'score': 1, }, ], [{'name': 'alex', 'score': 6, }, ], [{'name': 'dan', 'score': 3, }, ], ] )
[docs] def test_group_by_declarative(self) -> None: """ The simple **groupby** realization using a declarative approach """ result = {} for row in self.data2: key = row['name'] group = result.pop(key, []) group.append(row['score']) result[key] = group self.assertEqual( result, { 'john': [4], 'alex': [2, 6], 'dan': [1, 3], } ) self.assertEqual( list( map( lambda key: {'name': key, 'sum': reduce(add, result[key])}, result, ) ), [ {'name': 'john', 'sum': 4}, {'name': 'alex', 'sum': 8}, {'name': 'dan', 'sum': 4}, ] )
[docs] def test_group_by_declarative2(self) -> None: """ The simple **groupby** realization using a declarative approach """ result = {} for row in self.data2: key = row['name'] group = result.pop(key, []) group.append(row['score']) reduced = reduce( add, # It is very easy to change the function group ) result[key] = [reduced] print(result)
[docs] def test_group_by_declarative3(self) -> None: """ The simple **groupby** realization using a declarative approach """ result = {} for row in self.data2: key = row['name'] result[key] = result.get(key, 0) + row['score'] # 0 is the default value in the case of sum print(result)
[docs] def test_group_by_functional1(self) -> None: """ The simple **groupby** realization using a functional approach """ groups = reduce( lambda a, b: dict( **{b['name']: a.pop(b['name'], []) + [b['score']]}, **a, ), self.data2, {} ) result = list( map( lambda key: {'name': key, 'sum': reduce(add, groups[key])}, groups ) ) print(result)
[docs] def test_group_by_functional2(self) -> None: """ The simple **groupby** realization using a functional approach """ print( reduce( lambda a, b: dict( **{b['name']: [reduce(add, a.pop(b['name'], []) + [b['score']])]}, **a, ), self.data2, {} ) )