Last active
March 20, 2025 16:10
-
-
Save richard-scott/b2079f5578191eaa664b55fd64651134 to your computer and use it in GitHub Desktop.
My first AI derived bit of code...
This file contains hidden or 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
from ansible.errors import AnsibleFilterError | |
def remove_keys_recursive(original, remove): | |
if isinstance(original, dict): # Handling dictionaries | |
filtered_dict = {} | |
for key in sorted(original.keys()): # Sort keys alphabetically | |
value = original[key] | |
if key in remove: | |
if isinstance(value, dict) and isinstance(remove[key], dict): | |
# Recursively process nested dictionaries | |
filtered_value = remove_keys_recursive(value, remove[key]) | |
if filtered_value: # Keep only non-empty dictionaries | |
filtered_dict[key] = filtered_value | |
elif isinstance(value, list) and isinstance(remove[key], list): | |
# Remove specific values or dictionaries from the list | |
filtered_dict[key] = remove_items_from_list(value, remove[key]) | |
elif remove[key] is None: | |
continue # Fully remove this key | |
else: | |
filtered_dict[key] = remove_keys_recursive(value, remove.get(key, {})) | |
return dict(sorted(filtered_dict.items())) if filtered_dict else None # Sort final dict keys | |
elif isinstance(original, list): # Handling lists | |
return remove_items_from_list(original, remove) | |
return original # Return non-dict, non-list values as is | |
def remove_items_from_list(lst, remove_list): | |
""" | |
Removes elements from a list, including dictionaries, based on remove_list. | |
""" | |
if not isinstance(remove_list, list): | |
return lst # If remove_list isn't a list, do nothing | |
result = [] | |
for item in lst: | |
if isinstance(item, dict): | |
# Keep dictionary items that don't fully match any dictionary in remove_list | |
if not any(is_dict_match(item, remove_item) for remove_item in remove_list): | |
result.append(item) | |
else: | |
# Remove non-dict items directly | |
if item not in remove_list: | |
result.append(item) | |
return result | |
def is_dict_match(dict1, dict2): | |
""" | |
Checks if dict1 matches dict2 (i.e., if dict1 contains all key-value pairs in dict2). | |
""" | |
if not isinstance(dict1, dict) or not isinstance(dict2, dict): | |
return False # Only compare dicts | |
return all(k in dict1 and dict1[k] == v for k, v in dict2.items()) | |
def custom_filter(data, remove): | |
try: | |
return remove_keys_recursive(data, remove) | |
except Exception as e: | |
raise AnsibleFilterError(f"Error in filter: {e}") | |
class FilterModule(object): | |
def filters(self): | |
return { | |
'dict_recursive_remove': custom_filter | |
} | |
if __name__ == '__main__': | |
# Example Dictionary with Lists | |
original_dict = { | |
"a": [1, 2, 3, 4], | |
"b": { | |
"c": [5, 6, 7], | |
"d": [{"e": 10, "f": 20}, {"e": 30, "f": 40}] | |
}, | |
"g": [100, 200, 300] | |
} | |
remove_dict = { | |
"a": [2, 3], # Remove 2 and 3 from list "a" | |
"b": { | |
"c": [6], # Remove 6 from list "c" | |
"d": [{"e": 10}] # Remove dicts inside list where "e" == 10 | |
}, | |
"g": None # Remove the entire list "g" | |
} | |
filtered_dict = remove_keys_recursive(original_dict, remove_dict) | |
# Remove top-level empty dictionaries (if necessary) | |
filtered_dict = {k: v for k, v in filtered_dict.items() if v is not None} | |
print(filtered_dict) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment