""" AUTHOR: Khushal P Soonderji DATE: Saturday, 18th May, 2024 OBJECTIVE: To provide a quick set of functions to work with fuzzy logic. REFERENCES: 1) https://www.w3schools.com/python/python_json.asp DOWNLOADS: N/A """ # ***************************************************************************************************************** # ***** **** # *** IMPORT *** # ***** **** # ***************************************************************************************************************** # To make sibling directories accessible for imports: import sys sys.path.append(".") sys.path.append("..") # To apply fuzzy logic: from thefuzz import fuzz, process # To work with tabulated data: import pandas as pd # ***************************************************************************************************************** # ***** **** # *** MACROS / ONE-TIME INIT *** # ***** **** # ***************************************************************************************************************** # --- Nothing Yet # ***************************************************************************************************************** # ***** **** # *** VARIABLES *** # ***** **** # ***************************************************************************************************************** # --- Nothing Yet # ***************************************************************************************************************** # ***** **** # *** FUNCTIONS *** # ***** **** # ***************************************************************************************************************** def get_best_match( target, choices, threshold = 0.70, partial = False ): if partial: scorer = fuzz.partial_token_sort_ratio else: scorer = fuzz.ratio result = process.extractOne( target, choices, score_cutoff = threshold * 100, scorer = scorer ) try: return result[0] except: return None # --------------------------------------------------------------------------------------------------------------------- def rank(target, choices, partial = True): if partial: scorer = fuzz.partial_token_sort_ratio else: scorer = fuzz.ratio result = process.extract( target, choices, limit = len(choices), scorer = scorer ) result = pd.DataFrame(result, columns = ["choice", "closeness"]) result["closeness"] = result["closeness"] / 100.0 return result # --------------------------------------------------------------------------------------------------------------------- def match(targets, choices, threshold = 0.7, partial = False, allow_null = False): all_matches_df = None all_matches = {target: None for target in targets} something_is_null = False for target in targets: match_df = rank(target, choices, partial = partial) match_df["target"] = target if all_matches_df is None: all_matches_df = match_df else: all_matches_df = pd.concat([all_matches_df, match_df]) all_matches_df = all_matches_df.sort_values(by = ["closeness"], ascending = False).reset_index(drop = True) for target in targets: target_df = all_matches_df[all_matches_df["target"] == target].reset_index(drop = True) if target_df.empty: continue if target_df.at[0, "closeness"] >= threshold: choice = target_df.at[0, "choice"] all_matches[target] = choice all_matches_df = all_matches_df[all_matches_df["choice"] != choice] else: all_matches[target] = None something_is_null = True # print(all_matches) if something_is_null and not allow_null: return None else: return all_matches # ***************************************************************************************************************** # ***** **** # *** MAIN PROGRAM *** # ***** **** # ***************************************************************************************************************** if __name__ == "__main__": import async_json_utils awb_numbers = [ "SF1111BIC", "SF2222BIC", "SF3333BIC", "SF4444BIC", ] chat_text = "SF1112BIC" # print(chat_text == names[0]) best_match = get_best_match(chat_text, awb_numbers, threshold = 0.60, partial = False) print(f"Best match for '{chat_text}' is '{best_match}'")