У меня есть этот пример кода, и я пытаюсь отфильтровать совпадающие объекты, не увеличивая сложность или производительность кода:
Этот код здесь фильтрует совпадения на основе одного явно определенного ключа, и он не чувствителен к регистру.
const people = [
{ firstName: 'Bob', lastName: 'Smith', status: 'single' },
{ firstName: 'bobby', lastName: 'Suxatcapitalizing', status: 'single' },
{ firstName: 'Jim', lastName: 'Johnson', status: 'complicated' },
{ firstName: 'Sally', lastName: 'Fields', status: 'relationship' },
{ firstName: 'Robert', lastName: 'Bobler', status: 'single' },
{ firstName: 'Johnny', lastName: 'Johannson', status: 'complicated' },
{ firstName: 'Whaley', lastName: 'McWhalerson', status: 'relationship'
rogueBonusKey: 'bob likes salmon' },
]
const searchString = 'Bob'
const found = people.filter((person) => {
if (person.firstName === searchString) return true
})
console.log(found)
ЦЕЛЬ:
- Я хочу, чтобы он соответствовал регистру без учета регистра
- Я хочу, чтобы он возвращал совпадения с любого ключа
- Я хочу, чтобы он нашел, используя
contains
не точное совпадение
Что-то вроде этого:
// const people = [
// { firstName: 'Bob', lastName: 'Smith', status: 'single' },
// { firstName: 'bobby', lastName: 'Suxatcapitalizing', status: 'single' },
// { firstName: 'Jim', lastName: 'Johnson', status: 'complicated' },
// { firstName: 'Sally', lastName: 'Fields', status: 'relationship' },
// { firstName: 'Robert', lastName: 'Bobler', status: 'single' },
// { firstName: 'Johnny', lastName: 'Johannson', status: 'complicated' },
// { firstName: 'Whaley', lastName: 'McWhalerson', status: 'relationship'
// rogueBonusKey: 'bob likes salmon' },
// ]
// const searchString = 'bob'
// ... magic
// console.log(found)
// { firstName: 'Bob', lastName: 'Smith', status: 'single' },
// { firstName: 'bobby', lastName: 'Suxatcapitalizing', status: 'single' },
// { firstName: 'Robert', lastName: 'Bobler', status: 'single' },
// { firstName: 'Whaley', lastName: 'McWhalerson', status: 'relationship'
// rogueBonusKey: 'bob likes salmon' },
Я изучил документацию, связанную с Array.filter()
, и определенно могу найти решения, включающие Array.reduce()
и перебирающие вещи с помощью Object.keys(obj).forEach()
, но я хочу знать, есть ли краткий и эффективный способ справиться с таким нечетким поиском.
Что-то вроде этого:
const people = [
{ firstName: 'Bob', lastName: 'Smith', status: 'single' },
{ firstName: 'bobby', lastName: 'Suxatcapitalizing', status: 'single' },
{ firstName: 'Jim', lastName: 'Johnson', status: 'complicated' },
{ firstName: 'Sally', lastName: 'Fields', status: 'relationship' },
{ firstName: 'Robert', lastName: 'Bobler', status: 'single' },
{ firstName: 'Johnny', lastName: 'Johannson', status: 'complicated' },
{ firstName: 'Whaley', lastName: 'McWhalerson', status: 'relationship' },
rogueBonusKey: 'bob likes salmon' },
]
const searchString = 'Bob'
const found = people.filter((person) => {
if (person.toString().indexOf(searchString).toLowerCase !== -1) return true
})
console.log(found)
[edit] Это определенно работает, но приемлемо ли это?
const people = [
{ firstName: 'Bob', lastName: 'Smith', status: 'single' },
{ firstName: 'bobby', lastName: 'Suxatcapitalizing', status: 'single' },
{ firstName: 'Jim', lastName: 'Johnson', status: 'complicated' },
{ firstName: 'Sally', lastName: 'Fields', status: 'relationship' },
{ firstName: 'Robert', lastName: 'Bobler', status: 'single' },
{ firstName: 'Johnny', lastName: 'Johannson', status: 'complicated' },
{ firstName: 'Whaley', lastName: 'McWhalerson', status: 'relationship',
rogueBonusKey: 'bob likes salmon' },
]
const searchString = 'Bob'
const found = people.filter((person) => {
const savageMatch = JSON.stringify(person)
.toLowerCase()
.indexOf(searchString.toLowerCase()) !== -1
console.log(savageMatch)
if (savageMatch) return true
})
console.log(found)
Оптимизирован объем памяти:
const found = people.filter((person) => JSON.stringify(person)
.toLowerCase()
.indexOf(searchString.toLowerCase()) !== -1
)
Преобразовано в функцию:
const fuzzyMatch = (collection, searchTerm) =>
collection.filter((obj) => JSON.stringify(obj)
.toLowerCase()
.indexOf(searchTerm.toLowerCase()) !== -1
)
console.log(fuzzyMatch(people, 'bob'))
Здесь есть несколько отличных ответов; до сих пор я выбрал это для своих нужд фильтрации:
const people = [
{ imageURL: 'http://www.alice.com/goat.jpeg', firstName: 'Bob', lastName: 'Smith', status: 'single' },
{ firstName: 'bobby', lastName: 'Suxatcapitalizing', status: 'single' },
{ firstName: 'Jim', lastName: 'Johnson', status: 'complicated' },
{ firstName: 'Sally', lastName: 'Fields', status: 'relationship' },
{ firstName: 'Robert', lastName: 'Bobler', status: 'single' },
{ firstName: 'Johnny', lastName: 'Johannson', status: 'complicated' },
{
firstName: 'Ronald', lastName: 'McDonlad', status: 'relationship',
rogueBonusKey: 'bob likes salmon'
},
{
imageURL: 'http://www.bob.com/cats.jpeg', firstName: 'Whaley', lastName: 'McWhalerson', status: 'relationship',
rogueBonusKey: 'bob hates salmon'
},
]
const searchString = 'bob'
const options = {
caseSensitive: false,
excludedKeys: ['imageURL', 'firstName'],
}
const customFind = (collection, term, opts) => {
const filterBy = () => {
const searchTerms = (!opts.caseSensitive) ? new RegExp(term, 'i') : new RegExp(term)
return (obj) => {
for (const key of Object.keys(obj)) {
if (searchTerms.test(obj[key]) &&
!opts.excludedKeys.includes(key)) return true
}
return false
}
}
return collection.filter(filterBy(term))
}
const found = customFind(people, searchString, options)
console.log(found)
Я сделал так, чтобы он поддерживал чувствительность к регистру и исключал определенные клавиши.