Search code examples
javascriptarraysobjectdata-structures

Check if array of objects containg sub-array all have the same values


  for (let material of submission.materials) {
      const { docs } = await getDocs(
        query(collection(db, "materials"), where("name", "==", material.name))
      );
      const materialKpis = docs[0].data().kpis.map((kpi) => {
        return { kpis: kpi.id, value: kpi.value };
      });
      allKpis = [
        ...allKpis,
        {
          material: material.name,
          kpis: materialKpis,
        },
      ];
    }



[{"kpis": [{id: "A4yYU8r9hFxCgEDV77ps", value: 2}], "material": "Test Materiaal"}, 
     {"kpis": [{id: "A4yYU8r9hFxCgEDV77ps", value: 2}, {id: "HhoomonFUYGVv4H4RTj3", value: 3}], 
      "material": "Test Materiaal 2"}
    ]

I have this array of objects called allKpis, containing a nested array of KPI objects with an ID and a value. I want to create a function that would return

   [{"kpis": [{id: "A4yYU8r9hFxCgEDV77ps", value: 2}], "material": "Test Materiaal"}, 
     {"kpis": [{id: "A4yYU8r9hFxCgEDV77ps", value: 2}], 
      "material": "Test Materiaal 2"}
    ]

Since the other KpiId does not exist on all objects. How would i go about doing this?


Solution

  • You can:

    • Iterate allKpis and count how many occurrences you have of each ID
    • Filter that list of IDs to only keep those that have a count that is equal to the length of allKpis.
    • Turn this list into a Set.
    • Map the objects in allKpis and apply a filter to their kpis arrays, requiring that the id is in that set.

    Code to execute after your loop:

    const ids = new Set(
        Object.entries(
            allKpis.flatMap(({kpis}) => kpis.map(({id}) => id))
                   .reduce((acc, id) => (acc[id] = (acc[id] ?? 0) + 1, acc), {})
        ).filter(([id, count]) => count == allKpis.length)
         .map(([id]) => id)
    );
     
    allKpis = allKpis.map(o => ({
        ...o,
        kpis: o.kpis.filter(({id}) => ids.has(id))
    }));