Merge commit 'c7259cfe9f05532fb3ae49e0460c70012c6a00ce' as 'utils_v2'
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
"""
|
||||
|
||||
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}'")
|
||||
Reference in New Issue
Block a user