How can I filter an array containing varied object structures dynamically?

Viewed 50

My usage will contain 6 different object types (some which contain double nested arrays), and any possibility of number of entries, on the condition that an given entry is unique.

These objects do not have a consistent unique identifier (a unique identifier is applied in backend on submission).

here is an example of what the array may look like (only 2 object types):

arr = [
    {name:"aaa",time:15},
    {name:"aaa",time:22},
    
    {timeline: "250", chars[{a},{b},{c}]},
    {timeline: "220", chars[{d},{e},{f}]},
]
    
obj = {name:"aaa",time:22}

My intention is to gain a true or false based on if obj is inside arr

I have tried methods:

  1. I was suggested this method & it errors: #<Object> is not a function
console.log(arr.find(obj))
  1. I also found this suggestion but it will always return false even with the element present
console.log(arr.includes(object))
  1. I tried this method myself, though it will always fail.
console.log(arr.filter((element, index) => element === obj)

With attempt 4, If I was to compare name, this would be insufficient as unique time would be ignored missing valid entries.

If I was to pass every field, this would also not work as each object may or may not have the field and cause error.

Its not really possible to manually pre-filter filter into distinct categories, as every time a new type is added it will need manually adding to the filter.

If there is a library which could do this that you know of, please let me know as that would be perfect. Otherwise any other suggestions (excluding separating arrays) Would be greatly appreciated.

3 Answers

Use arr.some() to check if the required object is present in the array.

To compare the objects, a simpler way is to Stringify both the Objects and compare them.

const arr = [
    {name:"aaa",time:15},
    {name:"aaa",time:22},
    {name: "aaa", chars: ["a", "b", "c"]},
    {name: "bbb", chars: ["d", "e", "f"]},
]

const obj1 = {name:"aaa", time: 15}
const obj2 = {name:"aaa",chars: ["a", "b", "c"]}

console.log(arr.some((element) => JSON.stringify(element) === JSON.stringify(obj1)))   // true
console.log(arr.some((element) => JSON.stringify(element) === JSON.stringify(obj2)))   // true

Didn't give much thought on performance.

I didn't put much thought on performace here but this might help:

function checkObjectInArray(arr, obj) {
  const res = arr.some((el) => deepEqual(el, obj));
  console.log(res);
}

function deepEqual(obj1, obj2) {
  if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;
  for (let prop in obj1) {
    if (!obj2.hasOwnProperty(prop) || obj2[prop] !== obj1[prop]) {
      return false;
    }
  }
  return true;
}

in your case you can use it like:

arr = [
  { name: "aaa", time: 15 },
  { name: "aaa", time: 22 },

  { timeline: "250", data: ["2", "3", "4"] },
  { timeline: "251", data: ["2", "3", "4"] },  // what is chars[{d},{e},{f}] ?!
];

obj = { name: "aaa", time: 22 };

checkObjectInArray(arr, obj);

Observation : arr is not a valid array. Nested chars is not containing a valid value.

Solution : You can simply achieve the requirement by Just converting the JSON object into a JSON string and by comparing.

This solution works fine as you are just trying to find a single object in the passed arr.

Live Demo :

const arr = [
    {name:"aaa",time:15},
    {name:"aaa",time:22},  
    {timeline: "250", chars: [{a: 1},{b: 2},{c: 3}]},
    {timeline: "220", chars: [{d: 4},{e: 5},{f: 6}]},
];
    
const obj = {name:"aaa",time:22};

const res = JSON.stringify(arr).indexOf(JSON.stringify(obj)) !== -1 ? true : false;

console.log(res);

Related