我正在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)。
我该怎么做才能从单词的开头过滤掉?
答案 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);