Сравнение массивов и объектов для системы фильтрации

#javascript #lodash

#javascript #Lodash

Вопрос:

У меня есть два объекта / массива, которые мне нужно сравнить для системы фильтрации, и вот грубый набор данных:

 var books = [{
        'title': 'book a',
        'relatedIds': [1, 2],
        'authorId': 1,
    },{
        'title': 'book b',
        'relatedIds': [1, 2, 3, 4],
        'authorId': 2,
    },{
        'title': 'book a',
        'relatedIds': [1],
        'authorId': 3,
    }];

var filters = {
    'relatedIds' : [1, 2, 3],
    'author': [1, 2]
};
  

Что я ожидаю увидеть для вышеупомянутых фильтров, которые book a (имеют связанные идентификаторы 1 и 2 и идентификатор автора 1 из filter) и book b (имеют связанные идентификаторы 1, 2 и 3 и идентификатор автора 2 из filter).

Я бы не ожидал увидеть, book c поскольку, несмотря на то, что у него правильный связанный идентификатор, его автором является 3, которого нет в фильтре.

Я пытался использовать метод фильтрации Lodash:

 _.filter(books, (book) => {
    ....
  

Но я не вижу, как я могу выполнять сравнения на основе массивов из фильтра либо с массивом, либо с int / string в книгах.

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

1. На самом деле вы не показали, что вы пробовали при использовании фильтра Lodash.

Ответ №1:

Вы можете использовать filter, some и включает:

  • filter используется для получения только желаемого результата из исходных данных
  • some используется для проверки того, доступен какой-либо relatedId элемент в filters ‘s relativeId или нет
  • includes используется для проверки, доступно ли данное значение в массиве.

 var books = [{'title': 'book a','relatedIds': [1, 2],'authorId': 1,},{'title': 'book b','relatedIds': [1, 2, 3, 4],'authorId': 2,},{'title': 'book a','relatedIds': [1],'authorId': 3,}];

var filters = {
    'relatedIds' : [1, 2, 3],
    'author': [1, 2]
};

let op = books.filter(({relatedIds,authorId})=>(
   relatedIds.some(id=> filters.relatedIds.includes(id))
   amp;amp; filters.author.includes(authorId)
))
console.log(op)  

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

1. Это отличный ответ, вы не могли бы объяснить эту строку relatedIds.some(id=> filters.relatedIds.includes(id)) и что происходит?

2. @panthro добавьте объяснение, вы можете проверить

3. Спасибо, я все еще не уверен, почему вы используете some and then includes ? Конечно, some было бы достаточно проверить, доступен ли какой-либо relatedId элемент в фильтрах relativeId или нет?

4. @panthro поскольку relatedId в вашем data и filter также есть массив, поэтому вам нужно сравнивать каждое значение data's relatedId с filters relatedId , если вы не найдете совпадения

5. Неважно, теперь я понимаю, some элемент в relatedIds должен быть includes в filterIds , и только по крайней мере один из элементов должен пройти этот тест — правильно?

Ответ №2:

Используйте _.intesection() для поиска похожих элементов в relatedIds , проверяя длину результата (0, если похожих элементов нет). Используйте _.includes() , чтобы проверить, находится ли authorId в author массиве фильтров:

 const books = [{"title":"book a","relatedIds":[1,2],"authorId":1},{"title":"book b","relatedIds":[1,2,3,4],"authorId":2},{"title":"book a","relatedIds":[1],"authorId":3}];

const filters = {"relatedIds":[1,2,3],"author":[1,2]};

const result = _.filter(books, o =>
  _.intersection(o.relatedIds, filters.relatedIds).length amp;amp;
  _.includes(filters.author, o.authorId)
);

console.log(result);  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>