Search code examples
javascriptreactjsecmascript-6lodashecmascript-5

Find unique array of objects dynamically considering undefined values


I have a an array of objects in this format:

const myArray = [
 {
  one: 'A',
  two: 'AB'
 },
 {
  one: undefined,
  two: 'AB'
 },
 {
  one: 'A',
  two: 'BC'
 },
 {
  one: undefined,
  two: 'CC'
 },
]

I want the output in this particular format where if one is undefined but two is present in another object then ignore that object. e.g., output:

const outputMyArray = [
 {
  one: 'A',
  two: 'AB'
 },
 {
  one: 'A',
  two: 'BC'
 },
 {
  one: undefined,
  two: 'CC'
 },

The object keys are dynamically generated hence cannot be hardcoded and each object can have same numbers of keys as others. This I have tried but did not work:

const objectValuesList = myArray.map((obj: any) => Object.values(obj))

const uniqueStrigifiedList = Array.from(new Set( objectValuesList.filter((obj: any) => !obj.includes(undefined)).map((obj: any) => JSON.stringify(obj)) ))

myArray?.filter((obj: any) => !uniqueStrigifiedList?.includes( String(Object.values(obj)) ))

This solution does not seem to be working as it considers all object keys as unique.


Solution

  • You could take a two step approach:

    1. Get all object with no undefined as value and store the values with to an object.
    2. Check the objects with undefined and if not seen add this object to the result array.

    const
        data = [{ one: 'A', two: 'AB' }, { one: undefined, two: 'AB' }, { one: 'A', two: 'BC' }, { one: undefined, two: 'CC' }],
        keys = ['one', 'two'],
        result = [],
        seen = Object.fromEntries(keys.map(k => [k, {}])),
        withUndefined = [];
    
    for (const o of data) {
        if (keys.every(k => o[k] !== undefined)) {
            keys.forEach(k => seen[k][o[k]] = true);
            result.push(o);
        } else {
            withUndefined.push(o);
        }
    }
    
    for (const o of withUndefined) {
        if (keys.some(k => seen[k][o[k]])) continue;
        result.push(o);
    }
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }