I have a search bar which relies on this filter method. I concatenate all the search strings in a variable concat
, and then use either .includes()
or .match()
as shown below. If searched for multiple words, this only returns a result if the words occur consecutively in concat
.
However, I want it to match ANY two words in concat
, not just consecutive ones. Is there a way to do this easily?
.filter((frontMatter) => {
var concat =
frontMatter.summary +
frontMatter.title +
frontMatter.abc+
frontMatter.def+
frontMatter.ghi+
frontMatter.jkl;
return concat.toLowerCase().match(searchValue.toLowerCase());
});
Also tried;
.filter((frontMatter) => {
const concat =
frontMatter.summary +
frontMatter.title +
frontMatter.abc+
frontMatter.def+
frontMatter.ghi+
frontMatter.jkl;
return concat.toLowerCase().includes(searchValue.toLowerCase());
});
Thanks!
Everything is explained in the comments of the code.
.filter((frontMatter) => {
// Get the front matter into a string, separated by spaces
const concat = Object.values(frontMatter).join(" ").toLowerCase();
// Look for a string in quotes, if not then just find a word
const regex = /\"([\w\s\\\-]+)\"|([\w\\\-]+)/g;
// Get all the queries
const queries = [...searchValue.toLowerCase().matchAll(regex)].map((arr) => arr[1] || arr[2]);
// Make sure that every query is satisfied
return queries.every((q) => concat.includes(q));
});
.filter((frontMatter) => {
// Get the front matter into a string, separated by spaces
// The prepended and appended spaces are important for the regex later!
const concat = ` ${Object.values(frontMatter).join(" ").toLowerCase()} `;
// Look for a string in quotes, if not then just find a word
const regex = /\"([\w\s\\\-]+)\"|([\w\\\-]+)/g;
// Get all the queries
const queries = [...searchValue.toLowerCase().matchAll(regex)].map((arr) => arr[1] || arr[2]);
// Make sure that every query is satisfied
// [\\s\\.?!_] and [\\s\\.?!_] check for a space or punctuation at the beginning and end of a word
// so that something like "deter" isn't matching inside of "undetermined"
return queries.every((q) => new RegExp(`[\\s\\.?!_]${q}[\\s\\.?!_]`).test(concat));
});
I'd use .reduce
to count up the number of matches, and return true if there are at least 2:
const props = ['summary', 'title', 'abc', 'def', 'ghi', 'jkl'];
// ...
.filter((frontMatter) => {
const lowerSearch = searchValue.toLowerCase();
const matchCount = props.reduce(
(a, prop) => a + lowerSearch.includes(frontMatter[prop].toLowerCase()),
0
);
return matchCount >= 2;
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.