Фильтровать результаты по началу слова - PullRequest
1 голос
/ 23 апреля 2019

Я работаю над проектом на курсе ReactJS, и у меня возник вопрос.Я хочу искать результаты и фильтровать на основе НАЧАЛА слов, а не только строки, присутствующей где-либо в результате.

Например, в списке контактов ввод "r" может вернуть R ichard, Aa r on и Ba r ba r a, потому что все они содержат "r".Как мне сделать так, чтобы он отфильтровывал с начала слова и далее, как в словаре?

В настоящее время я фильтрую результаты из массива, используя управляемый компонент для динамического поиска и фильтрации результатов.Вот соответствующий фрагмент на данный момент:

filterResults = (venueFilter) => {
  let filteredVenues = this.state.venues
  filteredVenues = filteredVenues.filter((venue) => {
    let venueData = venue.name.toLowerCase();
    return venueData.indexOf(venueFilter.toLowerCase()) !== -1
  })
  this.setState({
    filteredVenues
  })
}

Проект вызывает рестораны рядом со мной.Но затем, набрав «r», вы узнаете много вещей, так как это обычное письмо, и потому что «ресторан» начинается с R. Ввод «М» вызывает и японский ресторан « M ИКАДО» (полезно / хорошо).UX), но также возвращает «Sia m Thai» и «Stadt m auer» (не особенно полезный / плохой UX).

Что я могу сделать, чтобы отфильтровать начало слова?

Ответы [ 5 ]

1 голос
/ 23 апреля 2019

Используйте startsWith вместо indexOf

filteredVenues = filteredVenues.filter(venue =>
  venue.name.toLowerCase().startsWith(venueFilter.toLowerCase())
)
0 голосов
/ 23 апреля 2019

Как насчет сортировки по первому вхождению? При этом сначала отображаются те, которые совпадают в начале:

 const result = venues
   .map(venue => ({ venue, score: venue.name.indexOf(search) }))
   .filter(it => it.score !== -1)
   .sort((a, b) => a.score - b.score)
   .map(it => it.venue);
0 голосов
/ 23 апреля 2019

Я думаю, что этот урок может помочь вам:

https://www.w3schools.com/howto/howto_js_autocomplete.asp

В фильтрованном поиске есть тот фрагмент кода, который делает то, что вы хотите (я думаю).

    inp.addEventListener("input", function(e) {
      var a, b, i, val = this.value;
      /*close any already open lists of autocompleted values*/
      closeAllLists();
      if (!val) { return false;}
      currentFocus = -1;
      /*create a DIV element that will contain the items (values):*/
      a = document.createElement("DIV");
      a.setAttribute("id", this.id + "autocomplete-list");
      a.setAttribute("class", "autocomplete-items");
      /*append the DIV element as a child of the autocomplete container:*/
      this.parentNode.appendChild(a);
      /*for each item in the array...*/
      for (i = 0; i < arr.length; i++) {
        /*check if the item starts with the same letters as the text field value:*/
        if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase()) {
          /*create a DIV element for each matching element:*/
          b = document.createElement("DIV");
          /*make the matching letters bold:*/
          b.innerHTML = "<strong>" + arr[i].substr(0, val.length) + "</strong>";
          b.innerHTML += arr[i].substr(val.length);
          /*insert a input field that will hold the current array item's value:*/
          b.innerHTML += "<input type='hidden' value='" + arr[i] + "'>";
          /*execute a function when someone clicks on the item value (DIV element):*/
              b.addEventListener("click", function(e) {
              /*insert the value for the autocomplete text field:*/
              inp.value = this.getElementsByTagName("input")[0].value;
              /*close the list of autocompleted values,
              (or any other open lists of autocompleted values:*/
              closeAllLists();
          });
          a.appendChild(b);
        }
      }
  });
0 голосов
/ 23 апреля 2019

Вам нужно регулярное выражение, которое может привязывать начало слова через \b флаг границы слова.

filteredVenues = filteredVenues.filter((venue) => {
    return new RegExp('/\\b'+venueFilter+'/', 'i').test(venue.name);
})

Обратите внимание, что нам также не нужно согласовывать строки в нижнем регистре,потому что при использовании флага i без учета регистра он будет совпадать в любом случае.

Sidenote: это пример использования «динамического» регулярного выражения, созданного для учета переменных.Это не было бы возможно с литералом REGEX, т. Е. Созданным не с конструктором new RegExp, а просто с /pattern/.

0 голосов
/ 23 апреля 2019

Вы можете использовать регулярное выражение, чтобы проверить, соответствуют ли строки требованию или нет

const data = [
 'MIKADO',
 'Siam Thai',
 'Stadtmauer',
 'Another',
 'Ane',
 'Anna',
];

// What the user typed for it's search
const search = 's';

// Build a regex using the searched string
// i for case insensitive
const regex = new RegExp(`^${search}`, 'i');

const filteredData = data.filter(x => regex.test(x));

console.log(filteredData);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...