9e8db857f4
git-subtree-dir: utils_v2 git-subtree-split: 3be5145c7a4cfede04d753324dfae31ace913c98
169 lines
5.9 KiB
Python
169 lines
5.9 KiB
Python
"""
|
|
|
|
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}'")
|