0

I have 2 arrays:

oldPerimeter:[
    {"meterID":"24348480450805","conso_prod":"Conso"},
    {"meterID":"24348769886471","conso_prod":"Conso"},
    {"meterID":"30002431659877","conso_prod":"Conso"},
]


newPerimeter:[
    {"meterID":"24348480450805","conso_prod":"Conso"},
    {"meterID":"30002431659877","conso_prod":"Conso"},
    {"meterID":"24327496366232","conso_prod":"Conso"},
    {"meterID":"24329232979894","conso_prod":"Conso"},
    {"meterID":"24328075237474","conso_prod":"Conso"}
]

I would like to get the element that are presents in oldPerimeter that are not present in newPerimeter

In my case, it should return:

elementsToDelete:[
   {"meterID":"24348769886471","conso_prod":"Conso"}
]

and if I do it from new to old, I should get:

elementsToCreate:[
   {"meterID":"24327496366232","conso_prod":"Conso"},
   {"meterID":"24329232979894","conso_prod":"Conso"},
   {"meterID":"24328075237474","conso_prod":"Conso"}
]

I could do it with a loop foreach, but I know there is a bunch of functions about arrays in Javascript, is there any better function that make the solution more elegant ?

I don't need an efficient way to do it, I will prefer an elegant way to do it

Juliatzin
  • 18,455
  • 40
  • 166
  • 325
  • 1
    What did you try and why is that not ok? – mplungjan Jun 18 '20 at 09:03
  • Is the `meterID` the prop that defines the difference or could there be a change in only the `conso_prod` ? – Gabriele Petrioli Jun 18 '20 at 09:03
  • @GabrielePetrioli equality means the 2 params are identicals. If same meterID as conso_prod = "Conso" and another with "Prod", they are considered as 2 differents elements – Juliatzin Jun 18 '20 at 09:07
  • @mplungjan I can do it easily with foreach, but I am looking for a more elegant way to do it. There is no "not ok" stuff here, just looking for improving my coding style with JS. I can code quickly a `foreach` way to do it, but I'm not sure it is interesting. – Juliatzin Jun 18 '20 at 09:10
  • 2
    Pretty soon, someone will post an answer suggesting the use of `filter()` with `find()`. Then someone else is going to comment saying that it's inefficient because the time complexity is O(m*n). Then someone will post an answer using a map or a lookup object. – Robby Cornelissen Jun 18 '20 at 09:13
  • Great. Right now, i don't care about inefficient, I prefer readability for that. I will add it in my question – Juliatzin Jun 18 '20 at 09:17
  • 1
    https://stackoverflow.com/questions/21987909/how-to-get-the-difference-between-two-arrays-of-objects-in-javascript/21989583 – Hendra Jun 18 '20 at 09:18

3 Answers3

0

You can use filter.

For finding the difference based on the specific properties of your sample arrays

const oldPerimeter = [
    {"meterID":"24348480450805","conso_prod":"Conso"},
    {"meterID":"24348769886471","conso_prod":"Conso"},
    {"meterID":"30002431659877","conso_prod":"Conso"},
];
const newPerimeter = [
    {"meterID":"24348480450805","conso_prod":"Conso"},
    {"meterID":"30002431659877","conso_prod":"Conso"},
    {"meterID":"24327496366232","conso_prod":"Conso"},
    {"meterID":"24329232979894","conso_prod":"Conso"},
    {"meterID":"24328075237474","conso_prod":"Conso"}
];

const diff = (source, target) => source.filter(({
  meterID: sourceMeterID,
  conso_prod: sourceConsoProd
}) => !target.find(({
  meterID: targetMeterID,
  conso_prod: targetConsoProd
}) => sourceMeterID === targetMeterID && sourceConsoProd === targetConsoProd))


console.log(diff(oldPerimeter, newPerimeter));
console.log(diff(newPerimeter, oldPerimeter));

It gets more involved when you want to compare more complex objects, like when having other nested objects/arrays.

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
0

A neat functional solution may be like this:

// Find elements in fromArray that are different from all elements in array
function disjunctive(array, fromArray) {
    return fromArray.filter(fromItem => {
        const fromJson = JSON.stringify(fromItem);
        return array.every(item => JSON.stringify(item) !== fromJson);
    })
}

Hope you figure it out how it works. Note that the JSON.stringify is a quick object deep equality trick with some caveats, prefer to use a better approach if needed.

Son Nguyen
  • 1,412
  • 4
  • 10
0

You could filter it. .some() returns true if the condition is met, so if it doesnt it returns false, so you need to negotiate it:

var oldPerimeter =[
    {"meterID":"24348480450805","conso_prod":"Conso"},
    {"meterID":"24348769886471","conso_prod":"Conso"},
    {"meterID":"30002431659877","conso_prod":"Conso"},
]


var newPerimeter =[
    {"meterID":"24348480450805","conso_prod":"Conso"},
    {"meterID":"30002431659877","conso_prod":"Conso"},
    {"meterID":"24327496366232","conso_prod":"Conso"},
    {"meterID":"24329232979894","conso_prod":"Conso"},
    {"meterID":"24328075237474","conso_prod":"Conso"}
]

function filterOut(from, to){
   return from.filter(({meterID}) => !to.some(el=> el.meterID === meterID));
}

let result = filterOut(oldPerimeter, newPerimeter);
let result2 = filterOut(newPerimeter, oldPerimeter);
console.log(JSON.stringify(result));
console.log(JSON.stringify(result2));
bill.gates
  • 14,145
  • 3
  • 19
  • 47