پاکسازی متن با تشخیص هویت فرق دارد
یک فرم ممکن است نامی با فاصلهٔ ابتدا، چند فاصلهٔ میانی یا تکرار کامل ارسال کند. هدف تمرین، یکسانکردن فاصله و حذف تکرار رشتهای است، نه تشخیص اینکه دو رکورد به یک انسان تعلق دارند. دو نفر میتوانند نام یکسان داشته باشند و یک نفر ممکن است نام را به چند شکل بنویسد. بنابراین این الگوریتم را نباید بدون شناسهٔ معتبر برای ادغام حساب کاربران به کار برد.
رفتار split و join را دقیق بفهمید
فراخوانی split بدون جداکننده، بخشهای سفید متوالی را از هم جدا میکند و بخش خالی ابتدا و انتها را نگه نمیدارد. join با یک فاصله، خروجی را دوباره میسازد. این روش هم tab و هم چند فاصله را پوشش میدهد. بااینحال نیمفاصله لزوماً همان فاصلهٔ سفید نیست؛ قرارداد این پروژه نیمفاصله یا املای نام را تغییر نمیدهد و فقط فاصلههای شناختهشده را سامان میدهد.
حفظ ترتیب با دو ساختار کوچک
فهرست خروجی برای نگهداشتن ترتیب اولین مشاهده مناسب است و یک set میتواند حضور قبلی نام را بررسی کند. هر نام پاکشده را فقط زمانی اضافه کنید که خالی نباشد و قبلاً در مجموعه دیده نشده باشد. استفاده از set بهتنهایی خروجی مناسبی برای ترتیب قراردادی نیست. از طرف دیگر، جستوجوی مکرر در یک فهرست بزرگ میتواند هزینهٔ بیشتری از عضویت در مجموعه داشته باشد.
حروف مشابه را خودسرانه تبدیل نکنید
ی و ي یا ک و ك ممکن است از نظر ظاهری نزدیک باشند اما کد Unicode متفاوت دارند. برای جستوجوی فارسی گاهی نگاشت صریح مفید است، ولی باید متن اصلی را برای نمایش نگه داشت. نرمالسازی Unicode نیز جای همهٔ تصمیمهای زبانی را نمیگیرد. در تمرین فعلی این نگاشت انجام نمیشود؛ بنابراین دو نام با شکل متفاوت حرف، دو رشتهٔ مستقل باقی میمانند.
کلید مقایسه را از متن نمایشی جدا کنید
اگر بعدها نرمالسازی گستردهتر خواستید، بهجای بازنویسی بیبازگشت نام، یک کلید مقایسهٔ جدا بسازید. مثلاً متن نمایشی میتواند همان چیزی باشد که شخص ثبت کرده و کلید جستوجو نسخهٔ پاکشدهٔ آن باشد. این طراحی هم قابلیت توضیح دارد و هم امکان اصلاح سیاست را نگه میدارد. هر نگاشت باید نمونهٔ مثبت و منفی داشته باشد تا دو نام متفاوت ناخواسته برابر نشوند.
آزمونهای کوچک ولی مهم
فهرست خالی، رشتهٔ تمامفاصله، نام تکراری با tab و نام دوبخشی را بررسی کنید. ترتیب خروجی باید با نخستین رخداد هر نام پاکشده برابر باشد؛ مرتبسازی الفبایی رفتار این پروژه نیست. یک نمونه با ي عربی و ی فارسی اضافه کنید تا معلوم شود کد بیش از قرارداد تغییر نمیدهد. همچنین تابع نباید فهرست ورودی را درجا تغییر دهد؛ برای تست، نسخهٔ قبل از اجرا را با بعد مقایسه کنید.
تمرین توسعه بدون ابهام
یک نسخهٔ توسعهیافته بسازید که علاوه بر نامها، تعداد رخداد هر نام پاکشده را گزارش کند. سپس تصمیم بگیرید متن نمایشی اولین رخداد باشد یا شکل انتخابی کاربر؛ این تصمیم را در آزمون بنویسید. اگر دادهٔ واقعی شامل نام اشخاص است، حداقل دادهٔ لازم را نگه دارید و گزارش عمومی نسازید. سادهبودن الگوریتم دلیل بیاهمیتبودن حریم خصوصی دادهٔ ورودی نیست.
نمونهکد و قرارداد پروژه
names: فهرست رشتهها؛ فاصلههای سفید پیدرپی با یک فاصله جایگزین، دو سر حذف، نام خالی حذف و نامهای برابر پس از همین پاکسازی یکتا شوند. شکل حروف تغییر نکند.
names: نامهای یکتا به ترتیب اولین رخداد؛ count: تعداد. این تمرین تطبیق هویت اشخاص نیست.
def solve(data):
names, seen = [], set()
for raw in data['names']:
name = ' '.join(raw.split())
if name and name not in seen:
seen.add(name)
names.append(name)
return {'names': names, 'count': len(names)}
print(solve({'names': [' سارا ', 'علی', 'سارا', ' علی ', 'مینا']}))خروجی مورد انتظار
{
"names": [
"سارا",
"علی",
"مینا"
],
"count": 3
}پرسشهای متداول
آیا خروجی set ترتیب قابل اتکا دارد؟
برای قرارداد حفظ اولین رخداد، به ترتیب پیمایش set تکیه نکنید؛ فهرست خروجی و مجموعهٔ seen نقشهای جدا دارند.
آیا نامهای برابر یعنی یک شخص؟
نه. برابری متن فقط یک ویژگی داده است و جای شناسهٔ حساب یا تأیید هویت را نمیگیرد.
تمرین عملی و قدم بعدی
پروژهٔ «پاکسازی فهرست نامها» همین قرارداد را در میزکار ارزیابی میکند. ابتدا خروجی نمونه را دستی محاسبه کنید، سپس تابع را اجرا کنید و یک ورودی مرزی متفاوت بسازید. نمونهکد راهی برای توضیح منطق است؛ برای یادگیری، علت هر شرط و انتخاب ساختار داده را بدون نگاهکردن به کد توضیح دهید. اجرای موفق با قبولی ارزیابی متفاوت است؛ نتیجه باید برای تمام حالتهای تعریفشده درست بماند.
منابع و مطالعهٔ بیشتر
برای بررسی جزئیات و ادامهٔ مطالعه؛ متن این راهنما مستقلاً برای نوونتیکس نوشته شده است.
