0

I have an array full of objects. Almost all objects have a different amount of keys value pairs. Some of these object have the same key value pairs.

Is there a nice way to remove all the sub-object-duplicates? (sub-object-duplicate = and object whose all key-value-pairs can be found in another object.)

In the example below e.g. it would remove the all middle objects and leave only the first and last one.

Many thanks in advance : )

The closest I got is using this from here, but I do not know how to add the if condition to only check for a property if it exists.

Unique by multiple properties ( id and name )

arr.filter((v,i,a)=>a.findIndex(t=>(t.id === v.id && t.name===v.name))===i)

Input

input = [
  {
    "key0": {
      "key1": "value1",
      "key2": "value1",
      "key3": "value1",
      "key4": "value1",
      "key5": "value1"
    }
  },
  {
    "key0": {
      "key1": "value1",
      "key3": "value1",
      "key5": "value1"
    }
  },
  {
    "key0": {
      "key1": "value1",
      "key2": "value1",
      "key3": "value1"
    }
  },
  {
    "key0": {
      "key1": "value1",
      "key2": "value1",
      "key5": "value1"
    }
  },
  {
    "key0": {
      "key1": "value1",
      "key2": "value2",
      "key3": "value2",
      "key4": "value2",
      "key5": "value2",
      "key6": "value2"
    },
  {
    "key0": {
      "key1": "value2",
      "key2": "value2",
      "key3": "value2",
      "key4": "value2",
      "key5": "value2",
      "key6": "value2"
    }
  }
]

Expected output

output = [
  {
    "key0": {
      "key1": "value1",
      "key2": "value1",
      "key3": "value1",
      "key4": "value1",
      "key5": "value1"
    }
  },
  {
    "key0": {
      "key1": "value2",
      "key2": "value2",
      "key3": "value2",
      "key4": "value2",
      "key5": "value2",
      "key6": "value2",
    }
  }
]

JilReg
  • 382
  • 1
  • 3
  • 16

2 Answers2

1

Here a very basic O(n2) complex solution:

var input = [
  {
    "key0": {
      "key1": "value1",
      "key2": "value1",
      "key3": "value1",
      "key4": "value1",
      "key5": "value1"
    }
  },
  {
    "key0": {
      "key1": "value1",
      "key3": "value1",
      "key5": "value1"
    }
  },
  {
    "key0": {
      "key1": "value1",
      "key2": "value1",
      "key3": "value1"
    }
  },
  {
    "key0": {
      "key1": "value1",
      "key2": "value1",
      "key5": "value1"
    }
  },
  {
    "key0": {
      "key1": "value1",
      "key2": "value2",
      "key3": "value2",
      "key4": "value2",
      "key5": "value2",
      "key6": "value2"
    }
  },
  {
    "key0": {
      "key1": "value2",
      "key2": "value2",
      "key3": "value2",
      "key4": "value2",
      "key5": "value2",
      "key6": "value2"
    }
  }
];

var isIncluded = function (a, b) {
 for (var key in a) {
   if (!b[key] || b[key] !== a[key])
     return false;
  }
  
  return true;
};


var output = [];

for (var i = 0; i < input.length; i++) {
 var toInclude = true;

  for (var j = 0; j < input.length; j++) {
   if (j === i)
     continue;
      
    if (isIncluded(input[i].key0, input[j].key0)) {
     toInclude = false;
      break;
    }
  }
  
  if (!toInclude)
   continue;
    
  output.push(input[i]);
}

console.log(output);
// document.write(JSON.stringify(output));

Note that the output gets 3 items since you may have made a mistake in one of your objects (mixing value1 and value2)

guillaumepotier
  • 7,369
  • 8
  • 45
  • 72
0

Here's a solution to handle every array with elem looks like {key0:{}},... to your needed format. The eg below handle more than just value1 and value2 : whatever the value ! :)

let input = [ { "key0": { "key1": "value1", "key2": "value1", "key3": "value1", "key4": "value1", "key5": "value1" } }, { "key0": { "key1": "value1", "key3": "value1", "key5": "value1" } }, { "key0": { "key1": "value1", "key2": "value1", "key3": "value1" } }, { "key0": { "key1": "value1", "key2": "value1", "key5": "value1" } }, { "key0": { "key1": "value1", "key2": "value2", "key3": "value2", "key4": "value2", "key5": "value2", "key6": "value2" } }, { "key0": { "key1": "value2", "key2": "value2", "key3": "value2", "key4": "value2", "key5": "value2", "key6": "value2" } } ];

function format(input) {

  let output = input.map(el => Object.keys(el)).map(ell => ell[0]);

  //check if only 'key0' at root key
  let same = output.reduce((acc, curr) => acc == curr ? output[0] : false, output[0]) == output[0];
  if (!same) return;

  //list all possibles value (value1, value2, ...)
  let possibleVal = {};
  for (key in input) {
    for (sub in input[key]['key0']) {
      possibleVal[input[key]['key0'][sub]] = null;
    }
  }
  possibleVal = Object.keys(possibleVal); // make it an array

  // fill output with possible values as key and fill with all possible values
  output = {};
  possibleVal.map(el => output[el] = {});
  input.map(el => {
    Object.entries(el['key0']).map(ell => {
      let key = ell[0];
      let value = ell[1]
      output[value][key] = value;
    });
  });

  // format it correctly and return it
  return possibleVal.map(val => ({
    'key0': output[val]
  }));
}

let final = format(input);

console.log(JSON.stringify(final, null, 4));
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Simon Dehaut
  • 2,271
  • 1
  • 8
  • 16