Created
October 2, 2024 07:53
-
-
Save danielgran/90ca5b04521b8e350c8c9cf9057a9989 to your computer and use it in GitHub Desktop.
Own Fiber Implementation, heavily inspired from the React Project. Converts General and Binaray trees, vice versa. Unit tests ~ 500 LOC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import uuid | |
class FiberNode: | |
def __init__(self, | |
name: str, | |
child=None, | |
sibling=None): | |
self.guid = uuid.uuid4() | |
self.name = name | |
self.child = child | |
self.sibling = sibling | |
def __repr__(self): | |
return f"[{self.name} -> {self.child} -> {self.sibling}]" | |
def __eq__(self, | |
other): | |
return self.__repr__() == other.__repr__() | |
def clean(self): | |
new_tree = clean_fiber_tree_recursively(self) | |
if new_tree is None: | |
return None | |
self.child = new_tree.child | |
self.sibling = new_tree.sibling | |
self.name = new_tree.name | |
return self | |
def clean_fiber_tree_recursively(fiber: FiberNode): | |
if fiber in [{}, None]: | |
return None | |
if isinstance(fiber, FiberNode): | |
fiber.child = clean_fiber_tree_recursively(fiber.child) | |
fiber.sibling = clean_fiber_tree_recursively(fiber.sibling) | |
if fiber.child in [None, dict()] and fiber.sibling is None: | |
return None | |
current_child_fiber = fiber.child | |
current_sibling_fiber = fiber.sibling | |
fiber.child = clean_fiber_tree_recursively(current_child_fiber) | |
if current_sibling_fiber: | |
if current_sibling_fiber.child in [{}, None]: | |
fiber.sibling = current_sibling_fiber.sibling | |
return fiber | |
def dict_to_fiber_tree(dic: dict): | |
''' | |
Converts a dictionary to a FiberTree. | |
Basically, this just is a function which converts a general tree to a binary tree. | |
:param dic: | |
:return: FiberNode | |
''' | |
if not dic: | |
return dic | |
if isinstance(dic, dict): | |
if len(dic) == 0: | |
raise ValueError("Empty dictionary") | |
current_root_fiber = FiberNode(name=list(dic.keys())[0]) | |
if len(dic) == 1: | |
current_root_fiber.child = dict_to_fiber_tree(list(dic.values())[0]) | |
return current_root_fiber | |
current_root_fiber.child = dict_to_fiber_tree(list(dic.values())[0]) | |
dic.pop(list(dic.keys())[0]) # only process the n+1 element further | |
current_root_fiber.sibling = dict_to_fiber_tree(dic) | |
return current_root_fiber | |
else: | |
return dic | |
def fiber_tree_to_dict_recursively(fiber: FiberNode): | |
if fiber is None: | |
return None | |
if not isinstance(fiber, FiberNode): | |
return fiber | |
if isinstance(fiber, dict): | |
return fiber | |
if not isinstance(fiber.child, FiberNode) and not fiber.sibling: | |
return {fiber.name: fiber.child} | |
result_dictionary = dict() | |
current_fiber = fiber | |
while current_fiber: | |
if isinstance(current_fiber, FiberNode): | |
result_dictionary[current_fiber.name] = fiber_tree_to_dict_recursively(current_fiber.child) | |
current_fiber = current_fiber.sibling | |
return result_dictionary |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment