1

I need to filter nested Objects by property values. I know similar questions have been asked before, but I couldn't find a solution for a case where the values were stored in an array.

In the provided code sample, I will need to filter the object based on tags. I would like to get objects which include "a" and "b" in the tags array.

const input1 = {
    "0":{
        "id":"01",
        "name":"item_01",
        "tags":["a","b"],
    },
    "1":{
        "id":"02",
        "name":"item_02",
        "tags":["a","c","d"],
    },
    "2":{
        "id":"03",
        "name":"item_03",
        "tags":["a","b","f"],
    }
}
 
function search(input, key) {
   return Object.values(input).filter(({ tags }) => tags === key);
}

console.log(search(input1, "a"));

As an output, I would like to receive the fallowing:

{
    "0":{
        "id":"01",
        "name":"item_01",
        "tags":["a","b"],
    },
    "2":{
        "id":"03",
        "name":"item_03",
        "tags":["a","b","f"],
    }
}

Thanks a lot in advance!

Manish Kumar
  • 595
  • 2
  • 15
FS-BA
  • 13
  • 3
  • Does this answer your question? [Filter array of objects based on another array in javascript](https://stackoverflow.com/questions/46894352/filter-array-of-objects-based-on-another-array-in-javascript) – pilchard Jul 19 '21 at 10:54

4 Answers4

1

Since you want to keep the object structure, you should use Object.entries instead of Object.values and to revert back to object type use Object.fromEntries:

Object.fromEntries(Object.entries(input).filter(...))

To make it work for multiple keys, use every in combination with includes as predicate:

keys.every(key => tags.includes(key))

const input1 = {
    "0":{
        "id":"01",
        "name":"item_01",
        "tags":["a","b"],
    },
    "1":{
        "id":"02",
        "name":"item_02",
        "tags":["a","c","d"],
    },
    "2":{
        "id":"03",
        "name":"item_03",
        "tags":["a","b","f"],
    }
}
 
function search(input, keys) {
   return Object.fromEntries(
   Object.entries(input).filter(([, { tags }]) => keys.every(key => tags.includes(key)))
   )
   
}

console.log(search(input1, ["a", "b"]));
marzelin
  • 10,790
  • 2
  • 30
  • 49
0
function search(input, key) {
  Object.values(input).filter(x=>x.tags.includes(key))
}
0

You can use Object.entries to get the [key, value] pair as an array of an array then you can use filter to filter out the elements that don't contain the element in the key array. Finally, you can use reduce to produce a single value i.e object as a final result

const input1 = {
  "0": {
    id: "01",
    name: "item_01",
    tags: ["a", "b"],
  },
  "1": {
    id: "02",
    name: "item_02",
    tags: ["a", "c", "d"],
  },
  "2": {
    id: "03",
    name: "item_03",
    tags: ["a", "b", "f"],
  },
};

function search(input, key) {
  return Object.entries(input)
    .filter(([, v]) => key.every((ks) => v.tags.includes(ks)))
    .reduce((acc, [k, v]) => {
      acc[k] = v;
      return acc;
    }, {});
}

console.log(search(input1, ["a", "b"]));
DecPK
  • 24,537
  • 6
  • 26
  • 42
0
   function search(input, tagsToFind) {
  return Object.values(input).filter(inputItem => {
    tagsToFind = Array.isArray(tagsToFind) ? tagsToFind : [tagsToFind];
    let tagFound = false;
    for (const key in tagsToFind) {
      if (Object.prototype.hasOwnProperty.call(tagsToFind, key)) {
        const element = tagsToFind[key];
        if (inputItem.tags.indexOf(element) === -1) {
          tagFound = false;
          break;
        } else {
          tagFound = true;
        }
      }
    }

    return tagFound;
  })

  // ({ tags }) => tags === key);
}

}