Vincent1989
Vincent1989

Reputation: 1657

How to separate the difference from an array object?

My existing array object are

//existing object
var existing = [
{
'ProviderCode':'aa',
'msg':'....',
},{
'ProviderCode':'bb',
'msg':'....',
},{
'ProviderCode':'cc',
'msg':'....',
},{
'ProviderCode':'dd',
'msg':'....',
},{
'ProviderCode':'ee',
'msg':'....',
}];
new object I'm comparing to
var new = [
{
'ProviderCode':'bb',
'msg':'....',
},{
'ProviderCode':'cc',
'msg':'....',
},{
'ProviderCode':'ee',
'msg':'....',
},{
'ProviderCode':'ff',
'msg':'....',
},{
'ProviderCode':'gg',
'msg':'....',
}];

I would like to generate same, remove and add array based on the two array objects, I can get the same array object but not the remove and add object from the objects.

var same = [];   //bb, cc, ee   //these will be the match
var remove = []; //aa , dd      //will be remove from existing
var add = [];    //ff, gg       //will be consider as add

//I can get the same using below:
e.forEach(function(ev,ei,ea){
n.forEach(function(nv,ni,na){
	if( ev.ProviderCode === nv.ProviderCode ){
		s.push({ProviderCode:ev.ProviderCode,msg:"Same, do nothing"});
    }
});
});
/* //output:
[{
"ProviderCode": "bb",
"msg": "Same, do nothing"
}, {
"ProviderCode": "cc",
"msg": "Same, do nothing"
}, {
"ProviderCode": "ee",
"msg": "Same, do nothing"
}]
*/


//but how do I get remove and add array object?

//remove will be:
/* //output:
[{
"ProviderCode": "aa",
"msg": "removed"
}, {
"ProviderCode": "dd",
"msg": "removed"
}]
*/

//add will be:
/* //output:
[{
"ProviderCode": "ff",
"msg": "added"
}, {
"ProviderCode": "gg",
"msg": "added"
}]
*/

Upvotes: 1

Views: 95

Answers (3)

Turtlefight
Turtlefight

Reputation: 10700

You can use Array.prototype.filter & Array.prototype.find for this:

let existing = [{ProviderCode:'aa'},{ProviderCode:'bb'},{ProviderCode:'cc'},{ProviderCode:'dd'},{ProviderCode:'ee'}];
let newData = [{ProviderCode:'bb'},{ProviderCode:'cc'},{ProviderCode:'ee'},{ProviderCode:'ff'},{ProviderCode:'gg'}];


let added = newData.filter(d => !existing.find(e => d.ProviderCode === e.ProviderCode));
console.log("ADDED:", added);

let removed = existing.filter(d => !newData.find(e => d.ProviderCode === e.ProviderCode));
console.log("REMOVED:", added);

let same = newData.filter(d => existing.find(e => d.ProviderCode === e.ProviderCode));
console.log("SAME:", same);

With a library like lodash this is a bit easier:

let existing = [{ProviderCode:'aa'},{ProviderCode:'bb'},{ProviderCode:'cc'},{ProviderCode:'dd'},{ProviderCode:'ee'}];
let newData = [{ProviderCode:'bb'},{ProviderCode:'cc'},{ProviderCode:'ee'},{ProviderCode:'ff'},{ProviderCode:'gg'}];

console.log("ADDED:"  , _.differenceBy(newData, existing, 'ProviderCode'));
console.log("REMOVED:", _.differenceBy(existing, newData, 'ProviderCode'));
console.log("SAME:"   , _.intersectionBy(newData, existing, 'ProviderCode'));
<script src="https://unpkg.com/[email protected]/lodash.min.js"></script>

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386560

You could take some sets and get the wanted items for each change.

const
    providerCode = ({ ProviderCode }) => ProviderCode;

var existingData = [{ ProviderCode: 'aa' }, { ProviderCode: 'bb' }, { ProviderCode: 'cc' }, { ProviderCode:'dd' }, { ProviderCode: 'ee' }],
    newData = [{ ProviderCode: 'bb' }, { ProviderCode: 'cc' }, { ProviderCode: 'ee' }, { ProviderCode: 'ff' }, { ProviderCode: 'gg' }],
    existingSet = new Set(existingData.map(providerCode)),
    newSet = new Set(newData.map(providerCode)),
    same = [...existingSet].filter(Set.prototype.has, newSet),
    add = [...newSet].filter(v => !existingSet.has(v)),
    remove = [...existingSet].filter(v => !newSet.has(v));

console.log(...same);
console.log(...add);
console.log(...remove);

Upvotes: 1

georg
georg

Reputation: 214949

You can use this little "library" that provides set operations for JS Map objects:

function mapUnion(m1, m2) {
    let m = new Map();

    for (let [k, v] of m1)
        m.set(k, v);
    for (let [k, v] of m2)
        m.set(k, v);

    return m;
}

function mapIntersection(m1, m2) {
    let m = new Map();

    for (let [k, v] of m1)
        if (m2.has(k))
            m.set(k, v);

    return m;
}

function mapDifference(m1, m2) {
    let m = new Map();

    for (let [k, v] of m1)
        if (!m2.has(k))
            m.set(k, v);

    return m;
}

Having this, you can convert both your arrays to Maps:

let m1 = new Map(oldArray.map(x => [x.ProviderCode, x]))
let m2 = new Map(newArray.map(x => [x.ProviderCode, x]))

and do whatever you want with these, for example,

console.log(mapIntersection(m1, m2))  // bb=>..., cc=>..., ee=>...
console.log(mapDifference(m1, m2))  // aa=>..., dd=>...

If you need arrays as results:

commonObjects = Array.from(mapIntersection(m1, m2).values())

Upvotes: 1

Related Questions