Vanilla JavaScript: фильтрация вложенного массива по массиву - PullRequest
0 голосов
/ 09 апреля 2020

Рассмотрим приведенный ниже массив сообщений:

posts_array =
[
 {
  id: 1,
  categories: [
   {
    category_id: 1,
    category_name: "one"
   },
   {
    category_id: 2,
    category_name: "two"
   },
 },
 {
  id: 2,
  categories: [
   {
    category_id: 1,
    category_name: "one"
   },
   {
    category_id: 3,
    category_name: "three"
   },
 },
 {
  id: 3,
  categories: [
   {
    category_id: 1,
    category_name: "one"
   },
   {
    category_id: 4,
    category_name: "four"
   },
   {
    category_id: 5,
    category_name: "five"
   },
 }    
]

У меня есть массив идентификаторов категорий, по которым я хочу отфильтровать указанный выше массив:

const category_id_array = [1, 4];

Я бы хотел фильтровать, чтобы были выполнены все условия, то есть возвращать элементы в posts_array, которые включают и category.category_id = 1 и category.category_id = 4

Я пытался с ниже (с функцией .some), но возвращает элементы, в которых выполняется любое условие, например либо Categories.category_id = 1 или Categories.category_id = 4

function filterPostsByCategoryIds(category_id_array){
    const filter_categories = category_id_array;
    const custom_filter = d => d.categories.some(c => filter_categories.includes(c.category_id));
    const filtered_posts_array = posts_array.filter(custom_filter);
    return filtered_posts_array;
}

Замена .some с .every вообще не возвращает никаких элементов.

Как я могу отфильтровать posts_array по category_id_array, чтобы он возвращал последний элемент в приведенном выше примере массива, т. Е. Где категории включают все category_id из category_id_array?

Спасибо и будьте в безопасности!

1 Ответ

1 голос
/ 09 апреля 2020

Вы можете использовать .every() на вашем category_id_array и возвращать true, если в текущем .categories есть объект .some(), у которого category_id равно значению текущего идентификатора (c) от вашего category_id_array:

const posts_array = [{ id: 1, categories: [{ category_id: 1, category_name: "one" }, { category_id: 2, category_name: "two" } ], }, { id: 2, categories: [{ category_id: 1, category_name: "one" }, { category_id: 3, category_name: "three" } ], }, { id: 3, categories: [{ category_id: 1, category_name: "one" }, { category_id: 4, category_name: "four" }, { category_id: 5, category_name: "five" } ], }];

function filterPostsByCategoryIds(category_id_array) {
  const custom_filter = d => category_id_array.every(c => d.categories.some(o => o.category_id === c));
  const filtered_posts_array = posts_array.filter(custom_filter);
  return filtered_posts_array;
}

const res = filterPostsByCategoryIds([1, 4]);
console.log(res);

Вы также можете создать набор category_id для каждого объекта, а затем использовать .every() с .has(), чтобы проверить, что массив категорий имеет каждый идентификатор из category_id вот так:

const posts_array = [{ id: 1, categories: [{ category_id: 1, category_name: "one" }, { category_id: 2, category_name: "two" } ], }, { id: 2, categories: [{ category_id: 1, category_name: "one" }, { category_id: 3, category_name: "three" } ], }, { id: 3, categories: [{ category_id: 1, category_name: "one" }, { category_id: 4, category_name: "four" }, { category_id: 5, category_name: "five" } ], }];

function filterPostsByCategoryIds(category_id_array) {
  return posts_array.filter(({categories}) => {
    const cat_ids = new Set(categories.map(({category_id}) => category_id));
    return category_id_array.every(id => cat_ids.has(id));
  });
}

const res = filterPostsByCategoryIds([1, 4]);
console.log(res);
...