diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b99b8a..0694461 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG +## 0.3.3 - 2023-6-9 +* Added a simple dict flattener utility class + ## 0.3.2 - 2021-5-31 ## 0.3.1 - 2021-5-31 * Fixed tests and published diff --git a/README.rst b/README.rst index 84b8277..0fccb2a 100755 --- a/README.rst +++ b/README.rst @@ -1,3 +1,3 @@ -dict-plus v0.0.4 +dict-plus Documentation: https://dict-plus.readthedocs.io/en/latest/ diff --git a/dict_plus/utils/simpleflatten.py b/dict_plus/utils/simpleflatten.py index 3343397..3d90091 100644 --- a/dict_plus/utils/simpleflatten.py +++ b/dict_plus/utils/simpleflatten.py @@ -1,3 +1,5 @@ +import math + class SimpleFlattener(object): """ @@ -7,20 +9,59 @@ class SimpleFlattener(object): would flatten to {"a_a1": 1, "a_a2": 2, "b_b1": 3, "b_b2": 4} - Another example: - {"a": [{"a1": [1], "a2": [2]},{"a1": [3] "a2": [4,5], "a3": [5]}] } - would flatten to - {"a_a1": [[1],[3]], "a_a2": [[2],[4,5]], "a_a3": [None, [5]]} - - Not meant to be a general dictionary flattener - + Not meant to be a general dictionary flattener TODO? """ - def __init__(self, simple_types=None): + class _SimpleListType(object): + """ + Helper class to distinguish a 'Simple List' a list of simple typed data + """ + def __init__(self, val): + self.val = val + + def __init__(self, simple_types=[], maxdepth=math.inf): + """ + simple_types is a list of types that should be treated as simple, base cases + maxdepth is the maximum depth within the data to traverse, defaults to no maximum + """ self.simple_types = {str, bytes, int, float, bool, tuple} + self.max_depth = maxdepth for s in simple_types: self.simple_types.add(s) - pass + def is_simplelist(self, val): + """ + Check if a list is only of simple_types and also not mixed types + """ + if isinstance(val, list): + list_types = set() + for element in val: + list_types.add(type(element)) + if len(list_types) == 1: # Only one type of element in the list + if list_types.pop() in self.simple_types: + return True + return False # Multiple types of data within the list, or data is not simple + else: + return False + + def flatten(self, data, current_depth=0, key_prefix=""): + if key_prefix: + key_prefix = f"{key_prefix}_" + + if current_depth > self.max_depth: + return {key_prefix: data} + + if isinstance(data, dict): + newdict = {} + for key, val in data.items(): + new_keyprefix = f"{key_prefix}{key}" + if type(val) in self.simple_types: + newdict[new_keyprefix] = val + else: + newdict.update(self.flatten(val, current_depth=current_depth+1, key_prefix=new_keyprefix)) + return newdict + elif isinstance(data, list): + if self.is_simplelist(data): + return {key_prefix: data} - pass + raise ValueError(f"SimpleFlatten cannot flatten data: '{data}'") diff --git a/setup.py b/setup.py index 5305aa7..b4c47e2 100755 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup import json -VERSION = "0.3.2" +VERSION = "0.3.3" def check_version_info(): diff --git a/version.json b/version.json index 58c4f2f..03bce3f 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "0.3.2" + "version": "0.3.3" }