我正在研究ReactJS课程中的一个项目,并且遇到了一个问题。我想搜索结果并根据单词的BEGINNING进行过滤,而不仅仅是结果中任何位置存在的字符串。
例如,在联系人列表中,键入“r”可能会返回Richard,Aaron和Barbara,因为它们都包含“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”带来了日本餐厅“MIKADO”(有用/良好的用户体验),但也返回“暹罗泰语“和”Stadtmauer“(不是特别有帮助/糟糕的用户体验)。
如何从单词的开头进行过滤?
使用startsWith
而不是indexOf
filteredVenues = filteredVenues.filter(venue =>
venue.name.toLowerCase().startsWith(venueFilter.toLowerCase())
)
您可以使用正则表达式来检查字符串是否符合要求
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);
你需要一个正则表达式,它可以通过\b
字边界标志锚定到一个单词的开头。
filteredVenues = filteredVenues.filter((venue) => {
return new RegExp('/\\b'+venueFilter+'/', 'i').test(venue.name);
})
注意我们也不需要将字符串协调为小写,因为通过使用i
不区分大小写的标志,它将匹配任何一种情况。
旁注:这是使用“动态”正则表达式的示例,该表达式是为了考虑变量而构建的。这对于REGEX文字来说是不可能的,即一个不是用new RegExp
构造函数而是用/pattern/
创建的。
我认为这个教程可能对你有所帮助:
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);
}
}
});
第一次出现排序怎么样?通过这一点,在开头匹配的那些首先出现:
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);