Совпадение строк Javascript по имени или фамилии, включая частичные

#javascript

#javascript

Вопрос:

Допустим, у меня есть список пользователей с firstName и lastName и я хочу отфильтровать тех, кто соответствует либо имени, либо фамилии, либо обоим, либо любым частям, независимо от пробелов. Как бы я построил этот фильтр?

Самое близкое, что я смог получить, это

 const userString = (user.firstName   user.lastName   user.email).toLowerCase().replace(/s/g,'');
return userString.includes(filterValue); // where filter value is the thing to test
 

Итак, если мы работаем с users = [John Smith, Adam Applebaum, Steve Wright] , и я набираю «jo» или «sm», я правильно получаю «John Smith», но если я наберу «josm», я бы также хотел «John Smith», но, похоже, я не могу вернуть это.

Как я могу создать фильтр или тест, чтобы включить в него как имя, так и фамилию или любую комбинацию.

Ответ @Nina ниже работал идеально, но мне пришлось немного изменить для моего конкретного варианта использования, моя окончательная реализация была;

   private _filter(value: string): User[] {
    if (!value || typeof value !== 'string') { return this.users; }
    const regexp = new RegExp([...(value.split(" "))].join('.*'), 'i');
    return this.users.filter(user => {
      const userString = user.firstName   ' '   user.lastName;
      return regexp.test(userString);
    });
  }
 

Комментарии:

1.попробуйте trim filtervalue , и я думаю, это должно сработать

2. includes выполняйте поиск последовательно, чтобы он соответствовал jo или so правильно, но он не будет совпадать josm , поскольку эти символы не появляются постоянно ни в одном из ваших имен пользователей, вам нужно использовать регулярное выражение с подстановочным знаком .*

3. josm Также должно совпадать Jako Some ?

Ответ №1:

Вы можете поместить каждый символ в пробел с помощью джокера и проверить строку.

 function filter(array, string) {
    return array.filter(RegExp.prototype.test, new RegExp([...string].join('.*'), 'i'));
}

var array = ['John Smith', 'Adam Applebaum', 'Steve Wright'];

console.log(filter(array, "jo"));
console.log(filter(array, "sm"));
console.log(filter(array, "josm")); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Комментарии:

1. потрясающее спасибо, мне пришлось немного изменить, чтобы работать в моем случае, но шаблон регулярных выражений был идеальным

Ответ №2:

@Nina Scholz пример отличный, но на самом деле я бы пошел немного другим путем, так как регулярное s.*m.*i.*t.*h выражение может дать немного неточные результаты.

например

Поиск: sh Результаты: Джон Смит
Поиск: st Результаты: Джон Смит
Поиск: Результаты ji: Джон Смит

На самом деле любая буква из имени и любая из фамилии, и в этом случае результаты являются неточными.

Я бы предпочел использовать регулярное .*SEARCH_PHRASE.* выражение или, если быть более точным .*smi.* , но это личное мнение 🙂 просто хотел показать различия.

Окончательная форма будет примерно такой:

 function buildPattern(str) {
    const arr = [...str];

    // as first item
    arr.splice(0, 0, '.*');

    // as last item
    arr.splice(arr.length, 0, '.*');

    return new RegExp(arr.join(''), 'i');
}

function filter(array, string) {
    return array.filter(RegExp.prototype.test, buildPattern(string));
}

const array = ['John Smith', 'Adam Applebaum', 'Steve Wright'];

console.log(filter(array, "jo"));
console.log(filter(array, "sm"));
console.log(filter(array, "josm")); 
 .as-console-wrapper { max-height: 100% !important; top: 0; }