按单词开头过滤结果

时间:2019-04-23 12:05:06

标签: javascript arrays reactjs sorting servlet-filters

我正在ReactJS课程中从事一个项目的工作,遇到一个问题。我想搜索结果并根据单词的BEGINNING进行过滤,而不仅仅是结果中任何位置出现的字符串。

例如,在联系人列表中,键入“ 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”会同时带来日式餐厅“ M IKADO”(帮助/ UX),但还会返回“ Sia m 泰语”和“ Stadt m auer”(不是特别有用/不好的UX)。

我该怎么做才能从单词的开头过滤掉?

5 个答案:

答案 0 :(得分:1)

使用startsWith代替indexOf

filteredVenues = filteredVenues.filter(venue =>
  venue.name.toLowerCase().startsWith(venueFilter.toLowerCase())
)

答案 1 :(得分:0)

您可以使用正则表达式检查字符串是否符合要求

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);

答案 2 :(得分:0)

您需要一个正则表达式,它可以通过\b单词边界标记锚定到单词的开头。

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

请注意,我们也不需要将字符串统一为小写形式,因为通过使用i不区分大小写的标志,它将在两种情况下都匹配。

旁注:这是一个使用“动态”正则表达式的示例,该正则表达式用于考虑变量。 REGEX文字不可能做到这一点,即不是使用new RegExp构造函数而是使用/pattern/创建的。

答案 3 :(得分:0)

我认为该教程可以为您提供帮助:

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);
        }
      }
  });

答案 4 :(得分:0)

如何按首次出现排序?通过这种方式,首先出现匹配的内容:

 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);