โจทย์: จากลิสต์ของสตริง ให้หาสตริงที่ "คล้าย" หรือ "เกี่ยวข้อง" กับสตริงเป้าหมาย (Target) โดยนิยามว่า สตริงหนึ่งขึ้นต้นด้วยอีกสตริงหนึ่ง (Prefix Match)
ตัวอย่าง
strings = ["Lion", "Li", "Tiger", "Tig"]
target = "Lion"
# ผลลัพธ์ที่คาดหวัง: "Lion", "Li"
# เพราะ "Lion".startswith("Li") == True
# และ "Li".startswith("Lion") == False แต่ "Lion".startswith("Li") == True
วิธีที่ 1: ใช้ startswith() (Prefix Match)
def find_prefix_matches(strings, target):
"""หาสตริงที่ขึ้นต้นด้วย target หรือ target ขึ้นต้นด้วยสตริงนั้น"""
matches = []
for s in strings:
if s.startswith(target) or target.startswith(s):
matches.append(s)
return matches
strings = ["Lion", "Li", "Tiger", "Tig", "Lionel", "Libert"]
target = "Lion"
print(find_prefix_matches(strings, target)) # ['Lion', 'Li', 'Lionel']
วิธีที่ 2: List Comprehension (Concise)
matches = [s for s in strings if s.startswith(target) or target.startswith(s)]
วิธีที่ 3: ใช้ difflib.get_close_matches (Fuzzy Matching)
สำหรับการหาคล้ายกันแบบ "ประมาณ" (Fuzzy/Similarity) ไม่ใช่แค่ Prefix
from difflib import get_close_matches strings = ["Lion", "Li", "Tiger", "Tig", "Lionel", "Line", "Lynx"] target = "Lion" # n=จำนวนผลลัพธ์, cutoff=ความคล้ายคลึง (0-1) matches = get_close_matches(target, strings, n=5, cutoff=0.6) print(matches) # ['Lion', 'Lionel', 'Line', 'Li', 'Lynx']
ตัวอย่างเพิ่มเติม: Typo Correction
from difflib import get_close_matches
commands = ["create", "delete", "update", "list", "show", "config"]
user_input = "creat" # พิมพ์ผิด
suggestions = get_close_matches(user_input, commands, n=3, cutoff=0.5)
print(f"Did you mean: {suggestions}?")
# Did you mean: ['create', 'config']?
วิธีที่ 4: ใช้ Levenshtein Distance (Edit Distance)
ติดตั้ง pip install python-Levenshtein หรือใช้ difflib.SequenceMatcher
from difflib import SequenceMatcher
def similarity(a, b):
return SequenceMatcher(None, a, b).ratio()
strings = ["Lion", "Li", "Tiger", "Tig", "Lionel", "Line"]
target = "Lion"
# เรียงตาม Similarity Score
ranked = sorted(strings, key=lambda s: similarity(target, s), reverse=True)
for s in ranked:
print(f"{s}: {similarity(target, s):.2f}")
# Output:
# Lion: 1.00
# Lionel: 0.77
# Line: 0.60
# Li: 0.57
# Lynx: 0.40
# Tiger: 0.00
การเลือกใช้งาน
| วิธี | เหมาะสำหรับ | Performance |
|---|---|---|
startswith | Prefix Match, Autocomplete, Command Completion | O(n*m) เร็วมาก |
difflib.get_close_matches | Fuzzy Search, Typo Correction, Spell Check | O(n*m) ปานกลาง |
Levenshtein/SequenceMatcher | Detailed Similarity Scoring, Ranking | O(n*m) ช้ากว่า |
RapidFuzz / TheFuzz | Production Fuzzy Search (Optimized C) | Very Fast |
สรุป
- ใช้
startswithสำหรับ Prefix Matching (Autocomplete, Command Suggestion) - ใช้
difflib.get_close_matchesสำหรับ Fuzzy Matching แบบง่าย ไม่ต้องติดตั้งเพิ่ม - ใช้
RapidFuzzหรือTheFuzzสำหรับ Production Fuzzy Search ที่ต้องการ Performance