Files
doczyai-pipelines/fieldProcessing/src/dict_operations.py
T
Michael McGuinness ae8abfd547 mv
2024-09-30 15:25:29 +01:00

107 lines
5.1 KiB
Python

import re
import json
from collections import defaultdict
def secondary_string_to_dict(dict_string):
"""
Converts a string representation of a dictionary into an actual dictionary object, handling potential formatting issues.
This function cleans the string by removing specific unwanted characters and markers that may interfere with JSON parsing.
It then locates the substring that correctly forms a dictionary format, attempts to parse it as JSON, and handles common
parsing errors by replacing problematic single quotes with double quotes before re-parsing.
Parameters:
dict_string (str): The string containing the dictionary-like content, potentially surrounded by extra text or characters.
Returns:
dict: The dictionary obtained from parsing the cleaned and corrected string.
"""
dict_string = dict_string.replace('<<<', '')
dict_string = dict_string.replace('>>>', '')
dict_string = dict_string.replace('\n', '') # Remove new line
start_index = dict_string.find('{')
end_index = dict_string.rfind('}') + 1
dict_substring = dict_string[start_index:end_index]
try:
result_dict = json.loads(dict_substring)
except:
dict_substring = dict_substring.replace("'", '"')
result_dict = json.loads(dict_substring)
return result_dict
def primary_string_to_dict(string_dict, filename):
"""
Converts a dictionary of strings, where each string represents multiple dictionary entries, into a list of dictionaries,
augmenting each with metadata such as page number and filename.
This function iterates over each page number's string data, extracting and converting string representations of
dictionaries into actual dictionary objects. It handles and cleans the string format to properly parse it into dictionaries.
All dictionaries are then augmented with their respective page number and the filename before being compiled into a list.
Parameters:
string_dict (dict): A dictionary where keys are page numbers and values are strings containing multiple dictionary entries.
filename (str): The filename associated with these entries, used to tag each resulting dictionary.
Returns:
list of dict: A list of dictionaries, each representing data extracted and converted from the input string, tagged with
their page number and filename.
"""
data = []
pattern = r'\{.*?\}'
for page_num in string_dict.keys():
primary_list = string_dict[page_num]
dicts = primary_list.split('[')[1] # Strip front
dicts = dicts.split(']')[0] # Strip back
dicts = dicts.replace('\n', '') # Remove new lines
dicts = dicts.replace('<<<', '')
dicts = dicts.replace('>>>', '')
dicts = re.sub(r"(?<!\\)'([^']*?)'(?<!\\):", r'"\1":', dicts)
dict_list = re.findall(pattern, dicts)
dict_list = [secondary_string_to_dict(d) for d in dict_list]
for dict_ in dict_list:
dict_['page_num'] = page_num
dict_['Filename'] = filename
data.append(dict_)
return data
def append_secondary(result_dicts):
"""
Aggregates and restructures a list of dictionaries by grouping based on specific fields and appending secondary and tertiary
entries for specific keys.
This function organizes dictionaries by creating a unique key from non-'REIMBURSEMENT' fields and groups them accordingly.
It then processes each group to combine entries, designating the first three as primary, secondary, and tertiary respectively
for any 'REIMBURSEMENT' related fields. The combined results are stored in new dictionaries reflecting this hierarchical structure.
Parameters:
result_dicts (list of dict): A list of dictionaries containing data with fields that may include several related to 'REIMBURSEMENT'.
Returns:
list of dict: A list of new dictionaries where each dictionary represents combined information from the original list,
with 'REIMBURSEMENT' fields clearly distinguished as primary, secondary, or tertiary.
"""
# Helper function to create a key from dict excluding certain keys
def create_key(d):
return tuple((k, d[k]) for k in d if not k.startswith('REIMBURSEMENT'))
# Group dictionaries by non-REIMBURSEMENT fields
grouped = defaultdict(list)
for d in result_dicts:
grouped[create_key(d)].append(d)
# Process groups to create combined entries
combined_results = []
for key, group in grouped.items():
# Create a new dictionary based on non-REIMBURSEMENT fields
new_dict = {k: v for k, v in key}
# Iterate over REIMBURSEMENT fields and assign them as primary, secondary, tertiary
for i, entry in enumerate(group[:3]): # Process only the first three entries
for k, v in entry.items():
if k.startswith('REIMBURSEMENT'):
new_key = f'{["PRIMARY", "SECONDARY", "TERTIARY"][i]}_{k}'
new_dict[new_key] = v
combined_results.append(new_dict)
return combined_results