Задача співбесіди: отримуємо email із рядка

Сьогодні ми розглянемо чергове завдання, яке дали на співбесіді, розв'яжемо завдання різними способами. Що ми вивчимо у цьому уроці:
- робота з рядками в JS,
- робота з регулярними виразами в JS,
- навчимося вирізати текст між потрібними символами за допомогою регулярних виразів.
Декілька слів про компанію. Невелика компанія. Штат програмістів приблизно 50-80 чоловік. Займається розробкою CRM для малого та середнього бізнесу. Завдання дається "як є". Тобто я не можу відповісти "що думала компанія" у цьому завданні. У ході рішення дозволяється користуватися інтернетом та пошуковою системою. Час на рішення – до 20 хвилин. Позиція – junior frontend dev.
Текст завдання
Поштові програми представляють email у двох стандартах - з урахуванням імені, яке користувач ввів у налаштуваннях поштової скриньки:
Volodimir Singapuk <singapuk.e03@gmail.com>
і просто email, так:
singapuk.e03@gmail.com
Завдання: написати рішення, яке може приймати рядок в одному з двох форматів і повертати тільки email. Уточнюємо:
Прийняли Volodimir Singapuk <singapuk.e03@gmail.com>
повернули singapuk.e03@gmail.com
Прийняли singapuk.e03@gmail.com
Повернули singapuk.e03@gmail.com
Виконаємо аналіз завдання. Умови не повні, тому не додумуватимемо додаткові складнощі, завдання зводиться до пошуку кутових лапок і, якщо вони є, то повертаємо тексту між ними. Валідація email виходить за рамки поточного завдання.
Як вирішували завдання кандидати
Після того, як співбесіду пройшли кілька десятків людей, можна помітити цікаву тенденцію. Спочатку всі кидалися розв`язували завдання за допомогою регулярних виразів. Дійсно, за допомогою пошуку та онлайн інструментів можна швидко отримати текст із кутовими дужками <singapuk.e03@gmail.com>, а далі ставало все цікавіше... Кандидат, після першого успіху, починає шукати як отримати текст між тегами за допомогою регулярних виразів і нічого не знаходив. Через 10 хвилин пошуку (не забувайте – загальний час 20 хвилин), у хід йшли методи роботи з рядком і текст просто вирізався. Потім кандидат дивився на код, розумів, що він не дуже гарний і переробляв код на роботу з рядком. Лише три кандидата розв`язали задачу тільки регулярними виразами.
Справді, завдання вирізати текст між символами за допомогою регулярних виразів, якщо ви з ними не працювали, є досить складним. Сьогодні ми його вирішимо, і ці знання ви зможете використовувати в інших завданнях.
Спосіб вирішення 1. Застосовуємо рядкові методи JS
Отже, ми маємо рядок і по ньому потрібно провести пошук кутових дужок. Якщо в тексті є "<", то можна шукати проводити вирізування тексту. Давайте зробимо.
let index = email.indexOf('<');
якщо index не дорівнює -1, то потрібно вирізати підрядок, який відповідає за email - із символу наступного ЗА index (що логічно, адже ми отримали індекс кутової дужки). Вирізати підрядок будемо до кінця рядка, за винятком останнього (символу ">").
email.substring(index + 1, email.length – 1);
в результаті рішення виглядає так:
const str1 = 'Volodimir Singapuk <singapuk.e03@gmail.com>';
const trimEmail = email => {
let index = email.indexOf('<');
if (index! == -1) {
return email.substring(index + 1, email.length – 1);
}
return email;
}
console.log(trimEmail(str1));
Перевіряємо, та переконуємося, що це рішення працює з двома видами email уявлень. І переходимо до наступного рішення.
Доповнення. За функцією видно, що тут і не потрібна валідація email. Якщо проводити валідацію, то логічно оформити її окремою функцією, яка буде виконуватися до функції trimEmail.
Спосіб вирішення 2. Вирізаємо текст між символами за допомогою регулярних виразів
Тепер – регулярки. Отримати email з рядка виду:
Volodimir Singapuk <singapuk.e03@gmail.com>
досить просто. Для цього можна просто ввести <S+>. Розшифруємо - кутові дужки думаю зрозуміло, \S символьний клас, який позначає непробільний символ. А символ плюс + квантифікатор, який показує, що непробільний символ зустрічається мінімум один раз або більше.
Перевірити цей патерн можна на сервісі regex101.com.
Поки що все виглядає просто. Але проблема в тому, що ми отримуємо email з кутовими дужками. А ось отримати текст між потрібними символами значно складніше. Потрібно знати, що шукати. І багато кандидатів на співбесіді витрачали час на пошук і не знаходили результату. Справді, шукати "випереджувальні та ретроспективні перевірки" буде не кожен. Так, у регулярних виразах є можливість шукати ПІСЛЯ символу та ДО символу. І називається це страшним виразом "випередження та ретроспектива".
Якщо спростити, то щоб позначити символ ПІСЛЯ якого ви хочете вести пошук, потрібно написати патерн виду ?<=символ, зазвичай символ пишуть з екрануванням, тобто так ?<=\символ. А символ ДО якого потрібно шукати пишуть патерном ?=символ, або з екрануванням ?=\символ. Якщо застосувати дані знання до нашого завдання, то доведеться написати наступний регулярний вираз:
(?<=\<)(\S+)(?=\>)
тобто. шукаємо між < > будь-який рядок не пробільних символів.
Перевірити можна також на regex101.
Найскладніше ми зробили. Тепер потрібно протестувати рядок на збіг із регулярним виразом. Для перевірки є два методи JavaScript, це test() і match(). Перший метод підходить для тестування і просто відповідає на питання є або нема збіга. А другий – повертає масив збігів. Оскільки в нас завдання повернути вирізаний тект - ідеально підходить другий метод. Вирішуємо. Спочатку введемо регулярку:
const regexp = /(?<=\<)(\S+)(?=\>)/g;
регулярний вираз в JavaScript вводиться між / /. Також додамо прапор g, тому що match() має два режими роботи. З прапором g він повертає масив збігів (що нам і потрібно), а без прапора - сирі дані. І виконуємо метод:
const matches = email.match(regexp);
Далі перевіряємо, якщо знайдено збіг, то буде повернено масив, якщо ні - null. І рішення стає таким:
const trimEmail = email => {
const regexp = /(?<=\<)(\S+)(?=\>)/g;
const matches = email.match(regexp);
if (mathes !== null) return matches[0];
return email;
}
console.log(trimEmail(str1));
Перевіряйте та переконайтеся, що код працює коректно з двома видами email.
Ось таке цікаве завдання, досить просте, але дозволяє зрозуміти логіку претендента.
Вміння користуватися випереджаючою та ретроспективною перевіркою у регулярних виразах дозволяє вам шукати текст між тегами у HTML коді, та дає дуже потужний інструмент для роботи з текстами.
Завантажити код можна тут. Також рекомендую подивитися, як вирішували завдання у телеграм каналі ItGid.