Запись фильтра Javascript с использованием нескольких массивов

#javascript #typescript #filter

Вопрос:

У меня есть тип объекта результата. Я хочу отфильтровать записи из объекта результата. У меня в форме есть 3 фильтра (Поиск по имени, городу, электронной почте). Все фильтры являются многовыборочными. Теперь я хочу отфильтровать свои записи результатов по приведенному выше массиву фильтров.

Пользователь отфильтрован по записям, использующим массив ниже

 var searchByname = ['john', 'test1'];
var searchByEmail = ['john@gmail.com', 'test1@gmail.com'];
var searchByCity = ['CA', 'LA'];
 

Фактический объект результата, из которого должен быть выполнен фильтр

 var result = [
    {
        'name': 'john',
        'email': 'john@gmail.com',
        'city': 'CA',
        'phone': 425663313
    },
    {
        'name': 'test1',
        'email': 'test1@gmail.com',
        'city': 'LA',
        'phone': 7418669633
    },
    {
        'name': 'Dyna',
        'email': 'Dyna@gmail.com',
        'city': 'New York',
        'phone': 12345666
    }
]
 

Я попробовал приведенное ниже решение, но оно фильтрует только любые записи одного фильтра

 var filteredArray_1 = result.filter(function(itm){
    return searchByname.indexOf(itm.name) > -1;
});
var filteredArray_2 = result.filter(function(itm){
    return searchByEmail.indexOf(itm.email) > -1;
});
var filteredArray_3 = result.filter(function(itm){
    return searchByCity.indexOf(itm.city) > -1;
});
let finalArray = [...filteredArray_1, ...filteredArray_2, ...filteredArray_3];
 

Ожидаемый Результат

 var result = [
    {
        'name': 'john',
        'email': 'john@gmail.com',
        'city': 'CA',
        'phone': 425663313
    },
    {
        'name': 'test1',
        'email': 'test1@gmail.com',
        'city': 'LA',
        'phone': 7418669633
    },
]
 

Ответ №1:

Ваш фильтр включает результаты любого проходящего фильтра и может включать результаты дважды.

Вместо этого примените все свои фильтры вместе:

 const searchByname = ['john', 'test1'];
const searchByEmail = ['john@gmail.com', 'test1@gmail.com'];
const searchByCity = ['CA', 'LA'];

const result = [
    {
        'name': 'john',
        'email': 'john@gmail.com',
        'city': 'CA',
        'phone': 425663313
    },
    {
        'name': 'test1',
        'email': 'test1@gmail.com',
        'city': 'LA',
        'phone': 7418669633
    },
    {
        'name': 'Dyna',
        'email': 'Dyna@gmail.com',
        'city': 'New York',
        'phone': 12345666
    }, 
    undefined, // Dummy test empty
    { } // Dummy test with no properties
];

const multifiltered = result.
    filter(itm => searchByname.indexOf(itm?.name) > -1).
    filter(itm => searchByEmail.indexOf(itm?.email) > -1).
    filter(itm => searchByCity.indexOf(itm?.city) > -1);
    
console.log('Multiple filters', multifiltered);

// However, your code will be easier to read if you do a single operation...

const filteredAND = result.
    filter(itm => 
        itm amp;amp;
        searchByname.indexOf(itm.name) > -1 amp;amp;
        searchByEmail.indexOf(itm.email) > -1 amp;amp;
        searchByCity.indexOf(itm.city) > -1);
        
console.log('AND filters', filteredAND);

const filteredOR = result.
    filter(itm => 
        itm amp;amp; (
        searchByname.indexOf(itm.name) > -1 ||
        searchByEmail.indexOf(itm.email) > -1 ||
        searchByCity.indexOf(itm.city) > -1));
        
console.log('OR filters', filteredOR); 

Комментарии:

1. Дает ли это мне результат, если один из моих фильтров равен нулю?

2. @UserPHP Нет, но его легко добавить item amp;amp; (...) вокруг предложения

3. Я не получаю возможность добавить его в текущий код

4. Фрагмент @UserPHP обновлен с проверками на пустоту

5. Из моих 3 фильтров, если только searchByname имеет значение, но два других не имеют никакого значения, они оба пусты, это работает?

Ответ №2:

Я не уверен, что полностью понимаю ваш вопрос.

но вы могли бы фильтровать таким образом

 var filtered = result.filter(
  (item) =>
    searchByname.includes(item.name) ||
    searchByEmail.includes(item.email) ||
    searchByCity.includes(item.city)
);
 

Это даст вам желаемый результат

Ответ №3:

Вы можете попробовать все это в зависимости от ваших требований,

 let andFiltered = result.filter(
  (data) =>
    searchByname.includes(data.name) amp;amp;
    searchByEmail.includes(data.email) amp;amp;
    searchByCity.includes(data.city)
);

console.log(andFiltered);

let orFiltered = result.filter(
  (data) =>
    searchByname.includes(data.name) ||
    searchByEmail.includes(data.email) ||
    searchByCity.includes(data.city)
);

console.log(orFiltered);