مسیرها
/
JavaScript
JavaScript
/
تمرین‌ها
/
چت‌بات باقاعده
چت‌بات باقاعده

چت‌بات باقاعده

تمرین یادگیری

مقدمه

عبارت‌های باقاعده در JavaScript

یک عبارت باقاعده (یا به اختصار Regex) دنباله‌ای از کاراکترهاست که می‌توانیم با آن عناصر خاصی از رشته‌ها را هدف بگیریم و دستکاری کنیم. از این رو می‌توانیم:

  • یک متن را در یک رشته جست‌وجو کنیم
  • زیررشته‌ها را در یک رشته جایگزین کنیم
  • اطلاعاتی را از یک رشته استخراج کنیم

💡 گونه‌ی عبارت‌های باقاعده در JavaScript بخشی از استاندارد ECMA-262 این زبان است. یعنی لازم نیست نگران سازگاری مخصوص هر مرورگر باشید.

چگونه عبارت‌های باقاعده بسازیم

در JavaScript، عبارت باقاعده بیشتر در قالب /pattern/modifiers نوشته می‌شود.

برای ساختن یک عبارت باقاعده دو راه داریم:

  1. لیترال عبارت باقاعده:
const regex = /[a-z]/;
  1. سازنده‌ی RegExp:
const regex = new RegExp('[a-z]');

در هر دو حالت، JavaScript از این عبارت باقاعده یک شیء می‌سازد. توصیه می‌شود الگوهای تغییرناپذیر را به کار ببرید و به‌صورت پیش‌فرض از لیترال استفاده کنید.

از سازنده‌ی RegExp می‌توان در مواردی استفاده کرد که عبارت باقاعده تغییر می‌کند یا هنوز آن را نمی‌دانیم (مثل ورودی).

🏴‍☠️ پرچم‌ها

عبارت‌های باقاعده قابلیت‌های اختیاری ویژه‌ای به نام flags دارند که امکانات بیشتری در اختیارمان می‌گذارند.

برخی از پرکاربردترین آن‌ها عبارت‌اند از:

  • /g - جست‌وجوی سراسری
  • /i - بدون حساسیت به بزرگی و کوچکی حروف
  • /m - جست‌وجوی چندخطی

در ادامه یک مثال ساده می‌آوریم:

const re = /home/gi;
const str = 'Home, sweet home.';
const myArray = str.match(re);
console.log(myArray);

=> // ["Home", "home"]

کاراکتر g به ما امکان می‌دهد همه‌ی تطبیق‌های ممکن را در یک رشته پیدا کنیم. بدون این ویژگی، JavaScript فقط نخستین تطبیق Home را استخراج می‌کرد.

پرچم /i که حساسیت به بزرگی و کوچکی حروف را نادیده می‌گیرد، هنگام یافتن یک الگو به ما انعطاف می‌دهد. به این ترتیب مهم نیست آنچه می‌جوییم با UPPERCASE نوشته شده باشد یا با lowercase.

وقتی از سازنده‌ی RegExp استفاده می‌کنید، نحوه‌ی نگارش افزودن پرچم‌ها متفاوت است.

let regex = /[a-z]/gi; // literal notation
let regex = new RegExp('[a-z]', 'gi'); // constructor with string pattern as first argument
let regex = new RegExp(/[a-z]/, 'gi'); // constructor with regular expression literal as first argument (Starting with ECMAScript 6)

پرکاربردترین توابع

وقتی عبارت‌های باقاعده با توابع درون‌ساز موجود در JavaScript ترکیب می‌شوند، ابزارهای قدرتمندی برای دستکاری رشته‌ها و گرفتن داده از آن‌ها در اختیار داریم.

این‌ها چند مورد از پرکاربردترین توابعی هستند که در کنار عبارت‌های باقاعده به کار می‌روند.

تست

متد test() جست‌وجویی برای یافتن تطبیق میان یک عبارت باقاعده و یک رشته‌ی مشخص انجام می‌دهد. «درست» یا «غلط» را برمی‌گرداند.

const str = 'It is difficult to test if you have a virus';
const result = /virus$/.test(str);

console.log(result);

// => true

تطبیق

با متد match() آرایه‌ای مفید به دست می‌آوریم که محتوای آن به وجود یا نبود تطبیق‌های یافته‌شده بستگی دارد.

به این ترتیب می‌توانیم هم در هر رشته‌ای جست‌وجو کنیم و هم اطلاعات را استخراج کنیم. برای نمونه:

const funnyQuote =
  'If you see someone crying, ask if it is because of their haircut.';
const regex1 = /someone/;
const regex2 = /happy/;

funnyQuote.match(regex1);
// => ["someone", index: 11, input: "If you see someone crying, ask if it is because of their haircut.", groups: undefined]

funnyQuote.match(regex2);
// => null

وقتی پرچم جست‌وجوی سراسری /g وجود داشته باشد، متد به‌جای گرفتن تنها تطبیق همراه با اطلاعات مفیدی مثل اندیس یا ورودی، همه‌ی موارد یافته‌شده را در قالب آرایه برمی‌گرداند:

const funnyQuote =
  'If you see someone crying, ask if it is because of their haircut.';

const regex3 = /if/gi;

funnyQuote.match(regex3);
// => ["If", "if"];

جایگزینی

متد replace() در JavaScript به ما امکان می‌دهد مقداری را در یک رشته‌ی مشخص جست‌وجو کنیم و آن را با مقدار تازه‌ی دلخواه جایگزین کنیم.

string.replace(searchValue, newValue);

الگویی که برای جست‌وجوی جایگزینی به کار می‌رود می‌تواند یک رشته‌ی ساده یا یک عبارت باقاعده باشد.

let string = 'I like dogs!';
let result = string.replace('dogs', 'cats');

let string = 'I would love to travel to Japan';
let result = string.replace(/Japan/g, 'Hawaii');

علاوه بر این، می‌توانیم در جایگاه مقدار جایگزین یک تابع به کار ببریم تا تغییرات بیشتری روی هر مقدار اعمال شود.

let text = 'Say hello to the chatbot.';
let result = text.replace(/chatbot|hello/gi, function (word) {
  return word.toUpperCase();
});
// => "Say HELLO to the CHATBOT"

تقسیم

متد split() در JavaScript روش دیگری برای استفاده از عبارت‌های باقاعده و دستکاری رشته‌هاست.

به این ترتیب، از عبارت باقاعده استفاده می‌کنیم تا یک رشته‌ی مشخص را بر اساس تشخیص یک الگو تقسیم کنیم، برای نمونه str.split(/[,.\s]/). این الگو به‌عنوان separator به کار می‌رود.

const str = 'hello,user.how are.you';

const result = str.split(/[,.\s]/);

console.log(result);
// => ['hello', 'user', 'how', 'are', 'you']

دستورالعمل‌ها

شما به عنوان متخصص «عبارت باقاعده» در شرکتی استخدام شده‌اید که در حال توسعه‌ی یک چت‌بات است.

این چت‌بات در مرحله‌ی بسیار ابتدایی توسعه قرار دارد؛ بنابراین ماموریت شما این است که با استفاده از عبارت‌های باقاعده، توانایی چت‌بات را در درک و تولید زبان طبیعی بهبود ببخشید.

بررسی معتبر بودن دستور

چت‌بات علاوه بر اینکه باهوش است، دستیاری وفادار هم هست.

برای پرسیدن سوالی از چت‌بات، کاربر باید واژه‌ی «Chatbot» را در جایگاه اول دستور بگوید.

اهمیتی ندارد که این کلیدواژه با حروف بزرگ نوشته شود یا با حروف کوچک. نکته‌ی مهم اینجا جایگاه واژه است.

تابع isValidCommand() را پیاده‌سازی کنید که به چت‌بات کمک می‌کند تشخیص دهد کاربر کِی دارد دستور می‌دهد.

isValidCommand("Chatbot, play a song from the 80's.";
// => True
isValidCommand("Hey Chatbot, where is the closest pharmacy?";
// => False
isValidCommand("CHATBOT, do you have a solution for this challenge?";
// => True

حذف ایموجی‌های رمزنگاری‌شده

چت‌بات در درک اینکه انسان‌ها چطور از ایموجی‌ها برای بیان احساساتشان استفاده می‌کنند مشکل دارد.

وقتی چت‌بات پیام‌های کاربر را دریافت می‌کند، هر ایموجی به صورت emoji و پس از آن شماره‌ی id آن نمایش داده می‌شود.

متد removeEmoji() را پیاده‌سازی کنید تا رشته‌ای را بگیرد و تمام رمزنگاری ایموجی‌ها را در سراسر پیام حذف کند.

خط‌هایی که متن ایموجی ندارند باید بدون تغییر برگردانده شوند.

فقط رشته‌ی ایموجی را حذف کنید. سعی نکنید فاصله‌ها را تنظیم کنید.

برای این چالش خاص، عبارت باقاعده را با نحوه‌ی نگارش سازنده بسازید.

removeEmoji("I love playing videogames emoji3465 it's one of my hobbies");
// => "I love playing videogames  it's one of my hobbies"

بررسی معتبر بودن شماره‌ی تلفن

با توجه به دانلود قابلیت‌های چت‌بات در یک اپلیکیشن موبایل، انتظار می‌رود کاربر در طول گفت‌وگو یک شماره تلفن بنویسد.

مشکل اینجاست که چت‌بات فقط می‌تواند شماره‌ای با قالب مشخص را بخواند و اعتبارسنجی کند.

اگر شماره معتبر باشد (با دنباله‌ی کاراکترهایی که عبارت باقاعده مشخص کرده است مطابقت داشته باشد)، چت‌بات با پیامی پاسخ می‌دهد که از کاربر تشکر می‌کند و شماره را تایید می‌کند. اگر شماره نامعتبر باشد، تابع به کاربر اطلاع می‌دهد که شماره‌ی تلفن معتبر نیست.

قالب مورد انتظار این است: (+##) ###-###-###

checkPhoneNumber('(+34) 659-771-594');
// => "Thanks! You can now download me to your phone."
checkPhoneNumber('659-771-594');
// => "Oops, it seems like I can't reach out to 659-771-594"

چت‌بات نرم‌افزاری واقعاً کنجکاو است. با اینکه می‌تواند در اینترنت درباره‌ی یک موضوع خاص جست‌وجو کند، دوست دارد از کاربران درباره‌ی وب‌سایت‌های جالب یا آدرس‌های وب بپرسد تا اطلاعات مرتبط را پیدا کند.

نمونه‌ای از گفت‌وگو:

  • چت‌بات: سلام، نام کاربری. دوست دارم یاد بگیرم چطور با JavaScript کدنویسی کنم. آیا وب‌سایت جالبی می‌شناسید که بتوانم در آن یاد بگیرم؟
  • کاربر: من چیزهای زیادی از exercism.org یاد گرفتم.

تابع getURL() را پیاده‌سازی کنید که بتواند آرایه‌ای شامل فقط لینک هر وب‌سایت را برگرداند. نوشتن یک عبارت باقاعده برای تشخیص هر آدرس وبی بسیار پیچیده می‌شود، اما چت‌بات فقط باید آدرس‌های وب ساده را بخواند. در این تمرین، آدرس وب هر دنباله‌ای از واژه‌هاست که با "." از هم جدا شده‌اند.

getURL(
  'I learned a lot from exercism.org and developer.mozilla.org, but I found ts39.es very boring!',
);
// => ["exercism.org", "developer.mozilla.org", "ts39.es"];

خوش‌آمدگویی به کاربر

چت‌بات برای ذخیره‌ی داده‌های همه‌ی افرادی که با آن‌ها گفت‌وگو کرده است، می‌تواند نام کامل را از پروفایل کاربر به این شکل بگیرد: «smith, john».

به این ترتیب، می‌خواهیم چت‌باتمان واقعاً مودب باشد و تأثیر خوبی بگذارد.

تابع niceToMeetYou() را بنویسید که رشته‌ای با نام کامل کاربر می‌گیرد و رشته‌ی «Nice to meet you, John Smith» را برمی‌گرداند.

برای یادگیری، تابع را با استفاده از متد جایگزینی از عبارت‌های باقاعده پیاده‌سازی کنید.

let str = 'Smith, John';

niceToMeetYou(str);
// => "Nice to meet you, John Smith"
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
JavaScript Exercism

آماده‌اید چت‌بات باقاعده را شروع کنید؟

در Exercism ثبت‌نام کنید تا JavaScript را همراه با 37 مفهوم159 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.