Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

Python: หาข้อความที่คล้ายกัน (Close Matches) จากลิสต์ด้วย startswith

โจทย์: จากลิสต์ของสตริง ให้หาสตริงที่ "คล้าย" หรือ "เกี่ยวข้อง" กับสตริงเป้าหมาย (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
startswithPrefix Match, Autocomplete, Command CompletionO(n*m) เร็วมาก
difflib.get_close_matchesFuzzy Search, Typo Correction, Spell CheckO(n*m) ปานกลาง
Levenshtein/SequenceMatcherDetailed Similarity Scoring, RankingO(n*m) ช้ากว่า
RapidFuzz / TheFuzzProduction Fuzzy Search (Optimized C)Very Fast

สรุป

  • ใช้ startswith สำหรับ Prefix Matching (Autocomplete, Command Suggestion)
  • ใช้ difflib.get_close_matches สำหรับ Fuzzy Matching แบบง่าย ไม่ต้องติดตั้งเพิ่ม
  • ใช้ RapidFuzz หรือ TheFuzz สำหรับ Production Fuzzy Search ที่ต้องการ Performance