Sort object by array within array? - javascript

I have a local storage that looks like this:
Key: Savedme
Value:
{
"Bob":["1","1"],
"John":["2","1"],
"Mom":["3","1"],
"Dad":["1","2"],
"Tom":["3","2"],
"Skipper42":["2","3"],
"Hated_41":["3","3"],
"Greeneggs":["2","2"],
"William":["1","3"]
}
I need to somehow sort it to look like this
{
"Bob":["1","1"],
"Dad":["1","2"],
"William":["1","3"]
"John":["2","1"],
"Greeneggs":["2","2"],
"Skipper42":["2","3"],
"Mom":["3","1"],
"Tom":["3","2"],
"Hated_41":["3","3"]
}
I've tried storing it in a matrix such as this:
var $runthrough = [[]];
$runthrough[$x,$y] = $values;
Where x is the first set of numbers, y is the next and then values is Bob, Dad etc...from there I could just do a foreach for both sections of the matrix and it would be done, HOWEVER when I use this method after it runs through one set of the objects, the second set gives an "undefined" even though I have setup some triggers to check and it's not actually going undefined.
var loadarray = JSON.parse(localStorage.getItem( 'savedme' ));
$.each(loadarray, function(k, v) {
if(typeof k === 'undefined' || !k){
console.error("undefined found at k!");
};
if(typeof v[0] === 'undefined' || !v[0]){
console.error("undefined found at x!");
};
if(typeof v[1] === 'undefined' || !v[1]){
console.error("undefined found at y!");
};
});
so I've come to realize, I'm probably doing something wrong with arrays so I figured it would be faster to sort out the array and THEN use the same function. It HAS to be ordered like this because it's basically going to be outputted to a matrix table, I tried ordering it like this:
{
"1":["1","Bob"],
"2":["1","John"],
}
but...the index value 1 would just be overwritten by the last value

You could chain the deltas of values with the same indices.
var a = [
{ "Bob": ["1", "1"] },
{ "John": ["2", "1"] },
{ "Mom": ["3", "1"] },
{ "Dad": ["1", "2"] },
{ "Tom": ["3", "2"] },
{ "Skipper42": ["2", "3"] },
{ "Hated_41": ["3", "3"] },
{ "Greeneggs": ["2", "2"] },
{ "William": ["1", "3"] }
];
a.sort(function (a, b) {
var aa = a[Object.keys(a)],
bb = b[Object.keys(b)];
if (aa[0] === bb[0]) {
return aa[1] - bb[1];
} else {
return aa[0] - bb[0];
}
});
document.querySelector("#demo").innerHTML = JSON.stringify(a, null, 4);
<div id="demo"></div>
Update 2021
const
array = [{ Bob: ["1", "1"] }, { John: ["2", "1"] }, { Mom: ["3", "1"] }, { Dad: ["1", "2"] }, { Tom: ["3", "2"] }, { Skipper42: ["2", "3"] }, { Hated_41: ["3", "3"] }, { Greeneggs: ["2", "2"] }, { William: ["1", "3"] }];
array.sort((a, b) => {
const
aa = Object.values(a)[0],
bb = Object.values(b)[0];
return aa[0] - bb[0] || aa[1] - bb[1];
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Objects properties do not have a guaranteed order in JavaScript, you need to use an Array.
Definition of an Object from ECMAScript Third Edition (pdf):
4.3.3 Object
An object is a member of the
type Object. It is an unordered collection of properties each of which
contains a primitive value, object, or
function. A function stored in a
property of an object is called a
method.
Try a data structure like this instead:
[
{ name: "Bob", value: ["1","1"] },
{ name: "Dad", value: ["1","2"] },
{ name: "William", value: ["1","3"] },
{ name: "John", value: ["2","1"] },
{ name: "Greeneggs", value: ["2","2"] },
{ name: "Skipper42", value: ["2","3"] },
{ name: "Mom", value: ["3","1"] },
{ name: "Tom", value: ["3","2"] },
{ name: "Hated_41", value: ["3","3"] }
]
You can generate this structure like this:
var loadarray = JSON.parse(localStorage.getItem( 'savedme' ));
var sorted = [];
for (var prop in loadarray) {
if (loadarray.hasOwnProperty(prop)) {
sorted.push({name:prop, value:loadarray[prop]});
}
}
sorted.sort(function(a, b) {
var v0 = a.value[0] - b.value[0];
return v0 == 0 ? a.value[0] - a.value[0] : v0;
});

Keys cannot be sorted within an object.
However, they can be processed in order using Object.keys(object).sort().
Here, I'm outputting the object to an array ā€“ sorted by the keys' values ā€“ then displaying that array:
var obj= {
"Bob":["1","1"],
"John":["2","1"],
"Mom":["3","1"],
"Dad":["1","2"],
"Tom":["3","2"],
"Skipper42":["2","3"],
"Hated_41":["3","3"],
"Greeneggs":["2","2"],
"William":["1","3"]
}
var arr= Object.keys(obj)
.sort(function(a, b) {
if(obj[a][0]===obj[b][0]) {
return obj[a][1] - obj[b][1];
}
else {
return obj[a][0] - obj[b][0];
}
})
.map(function(key) {
var o= {};
o[key]= obj[key];
return o;
});
document.body.innerHTML= JSON.stringify(arr);

Very late, but you can try this, assuming if you have an array:
var data=[{Value:
{
"Bob":["1","1"],
"John":["2","1"],
"Mom":["3","1"],
"Dad":["1","2"],
"Tom":["3","2"],
"Skipper42":["2","3"],
"Hated_41":["3","3"],
"Greeneggs":["2","2"],
"William":["1","3"]
}}];
data.forEach((elem)=>{
for(const property in elem.Value){
var k = elem.Value[property];
k.sort((a,b)=>a-b);
}
});
console.log(data);

Related

How to merge objects and append it into new array if object values are same using JavaScript?

I have this kind of data, my goal is to find all same request_id values in the given objects, merge it to one object and append its unique_id into one array, How can I get this result?
let fakeData = {
"622b1e4a8c73d4742a66434e212":{
request_id: "1",
uique_id:'001'
},
"622b1e4a8c73d4742a6643423e54":{
request_id: "1",
uique_id:'002'
},
"622b1e4a8c73d4742a6643423e23":{
request_id: "2",
uique_id:'003'
},
}
let parts = []
for (const property in fakeData) {
console.log(fakeData[property]);
}
//Result should be
// [{request_id:'1', values:["001, 002"]}, {request_id:'2', values:["003"]}]
You can iterate over all the values using Object.values() and array#reduce. In the array#reduce group based on request_id in an object and extract all the values of these object using Object.values().
const fakeData = { "622b1e4a8c73d4742a66434e212": { request_id: "1", uique_id: '001' }, "622b1e4a8c73d4742a6643423e54": { request_id: "1", uique_id: '002' }, "622b1e4a8c73d4742a6643423e23": { request_id: "2", uique_id: '003' }, },
output = Object.values(fakeData).reduce((r, {request_id, uique_id}) => {
r[request_id] ??= {request_id, values: []};
r[request_id].values.push(uique_id);
return r;
},{}),
result = Object.values(output);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Create array of objects from sorting another array of objects

I want to create an array of objects, and the first elements from the each data object to be a separate object, the second element from the each data object to be another separate object and so on...
let array = [{
data: {
center1: "1",
storage1: "1",
system1: "1",
}
},
{
data: {
center2: "2",
storage2: "2",
system2: "2",
}
}
]
Expected result:
[
{ center1: "1", center2: "2"},
{ storage1: "1", storage2: "2"},
{ system1: "1", system2: "2"}
]
And this is what I tried do to but is not working really well:)
const rows = [];
array.forEach((item, index) => {
for (let key in item.data) {
rows.push({index : key + ': ' + item.data[key]});
}
});
The output is this:
[
{index : 'center1: 1'},
{index : 'storage1: 1'},
{index : 'system1: 1'},
{index : 'center2: 2'},
{index : 'storage2: 2'},
{index : 'system2: 2'}
]
Thank you for your help!
This'll be incredibly brittle, because key ordering is irrelevant to how JS objects work, and the assumption that "the first key in each object is the same kind of key" is really only that: an assumption. So, the first thing to fix would be to make all those objects use the same keys, not uniques, thus making "key ordering" irrelevant.
However, if that's not an option (and it almost certain is, but if it's not) then Object.entries will turn any object into a key/value array, which you can then use to restructure this data:
let array = [{
data: {
center1: "1",
storage1: "1",
system1: "1",
}
},
{
data: {
center2: "2",
storage2: "2",
system2: "2",
}
}
]
const restructured = array.reduce((result, e) => {
Object.entries(e.data).forEach(([key, val], pos) => {
if (!result[pos]) result[pos] = {};
result[pos][key] = val;
});
return result;
}, []);
console.log(restructured);
You can try something like this, which may probably optimized (of course it will work only if all objects strictly have the same structure) :
const array = [
{
data: {
center1 : "1",
storage1: "1",
system1 : "1",
}
},
{
data: {
center2 : "2",
storage2: "2",
system2 : "2",
}
}
];
const finalArray = [];
for (let i = 0; i < Object.keys(array[0].data).length; i++) {
finalArray.push({});
array.forEach(arrayItem => {
finalArray[i][Object.keys(arrayItem.data)[i]] = Object.values(arrayItem.data)[i]
});
}
console.log(finalArray)
let array = [{
data: {
center1: "1",
storage1: "1",
system1: "1",
}
},
{
data: {
center2: "2",
storage2: "2",
system2: "2",
}
}
]
const rows = [];
array.forEach(item => {
Object.keys(item.data).forEach( (dt, i) => {
if ( ! rows[i] ) {
rows.push({});
}
rows[i][dt] = item.data[dt];
});
});
console.log(rows)

Javascript - removing elements on array [duplicate]

I have two result sets like this:
// Result 1
[
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
{ value: "4", display: "Ryan" }
]
// Result 2
[
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
]
The final result I need is the difference between these arrays ā€“ the final result should be like this:
[{ value: "4", display: "Ryan" }]
Is it possible to do something like this in JavaScript?
Using only native JS, something like this will work:
const a = [{ value:"0", display:"Jamsheer" }, { value:"1", display:"Muhammed" }, { value:"2", display:"Ravi" }, { value:"3", display:"Ajmal" }, { value:"4", display:"Ryan" }];
const b = [{ value:"0", display:"Jamsheer", $$hashKey:"008" }, { value:"1", display:"Muhammed", $$hashKey:"009" }, { value:"2", display:"Ravi", $$hashKey:"00A" }, { value:"3", display:"Ajmal", $$hashKey:"00B" }];
// A comparer used to determine if two entries are equal.
const isSameUser = (a, b) => a.value === b.value && a.display === b.display;
// Get items that only occur in the left array,
// using the compareFunction to determine equality.
const onlyInLeft = (left, right, compareFunction) =>
left.filter(leftValue =>
!right.some(rightValue =>
compareFunction(leftValue, rightValue)));
const onlyInA = onlyInLeft(a, b, isSameUser);
const onlyInB = onlyInLeft(b, a, isSameUser);
const result = [...onlyInA, ...onlyInB];
console.log(result);
For those who like one-liner solutions in ES6, something like this:
const arrayOne = [
{ value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer" },
{ value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed" },
{ value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi" },
{ value: "e97339e1-939d-47ab-974c-1b68c9cfb536", display: "Ajmal" },
{ value: "a63a6f77-c637-454e-abf2-dfb9b543af6c", display: "Ryan" },
];
const arrayTwo = [
{ value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer"},
{ value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed"},
{ value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi"},
{ value: "e97339e1-939d-47ab-974c-1b68c9cfb536", display: "Ajmal"},
];
const results = arrayOne.filter(({ value: id1 }) => !arrayTwo.some(({ value: id2 }) => id2 === id1));
console.log(results);
You could use Array.prototype.filter() in combination with Array.prototype.some().
Here is an example (assuming your arrays are stored in the variables result1 and result2):
//Find values that are in result1 but not in result2
var uniqueResultOne = result1.filter(function(obj) {
return !result2.some(function(obj2) {
return obj.value == obj2.value;
});
});
//Find values that are in result2 but not in result1
var uniqueResultTwo = result2.filter(function(obj) {
return !result1.some(function(obj2) {
return obj.value == obj2.value;
});
});
//Combine the two arrays of unique entries
var result = uniqueResultOne.concat(uniqueResultTwo);
import differenceBy from 'lodash/differenceBy'
const myDifferences = differenceBy(Result1, Result2, 'value')
This will return the difference between two arrays of objects, using the key value to compare them. Note two things with the same value will not be returned, as the other keys are ignored.
This is a part of lodash.
I take a slightly more general-purpose approach, although similar in ideas to the approaches of both #Cerbrus and #Kasper Moerch. I create a function that accepts a predicate to determine if two objects are equal (here we ignore the $$hashKey property, but it could be anything) and return a function which calculates the symmetric difference of two lists based on that predicate:
a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"}, { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}]
b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}]
var makeSymmDiffFunc = (function() {
var contains = function(pred, a, list) {
var idx = -1, len = list.length;
while (++idx < len) {if (pred(a, list[idx])) {return true;}}
return false;
};
var complement = function(pred, a, b) {
return a.filter(function(elem) {return !contains(pred, elem, b);});
};
return function(pred) {
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
};
}());
var myDiff = makeSymmDiffFunc(function(x, y) {
return x.value === y.value && x.display === y.display;
});
var result = myDiff(a, b); //=> {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}
It has one minor advantage over Cerebrus's approach (as does Kasper Moerch's approach) in that it escapes early; if it finds a match, it doesn't bother checking the rest of the list. If I had a curry function handy, I would do this a little differently, but this works fine.
Explanation
A comment asked for a more detailed explanation for beginners. Here's an attempt.
We pass the following function to makeSymmDiffFunc:
function(x, y) {
return x.value === y.value && x.display === y.display;
}
This function is how we decide that two objects are equal. Like all functions that return true or false, it can be called a "predicate function", but that's just terminology. The main point is that makeSymmDiffFunc is configured with a function that accepts two objects and returns true if we consider them equal, false if we don't.
Using that, makeSymmDiffFunc (read "make symmetric difference function") returns us a new function:
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
This is the function we will actually use. We pass it two lists and it finds the elements in the first not in the second, then those in the second not in the first and combine these two lists.
Looking over it again, though, I could definitely have taken a cue from your code and simplified the main function quite a bit by using some:
var makeSymmDiffFunc = (function() {
var complement = function(pred, a, b) {
return a.filter(function(x) {
return !b.some(function(y) {return pred(x, y);});
});
};
return function(pred) {
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
};
}());
complement uses the predicate and returns the elements of its first list not in its second. This is simpler than my first pass with a separate contains function.
Finally, the main function is wrapped in an immediately invoked function expression (IIFE) to keep the internal complement function out of the global scope.
Update, a few years later
Now that ES2015 has become pretty well ubiquitous, I would suggest the same technique, with a lot less boilerplate:
const diffBy = (pred) => (a, b) => a.filter(x => !b.some(y => pred(x, y)))
const makeSymmDiffFunc = (pred) => (a, b) => diffBy(pred)(a, b).concat(diffBy(pred)(b, a))
const myDiff = makeSymmDiffFunc((x, y) => x.value === y.value && x.display === y.display)
const result = myDiff(a, b)
//=> {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}
In addition, say two object array with different key value
// Array Object 1
const arrayObjOne = [
{ userId: "1", display: "Jamsheer" },
{ userId: "2", display: "Muhammed" },
{ userId: "3", display: "Ravi" },
{ userId: "4", display: "Ajmal" },
{ userId: "5", display: "Ryan" }
]
// Array Object 2
const arrayObjTwo =[
{ empId: "1", display: "Jamsheer", designation:"Jr. Officer" },
{ empId: "2", display: "Muhammed", designation:"Jr. Officer" },
{ empId: "3", display: "Ravi", designation:"Sr. Officer" },
{ empId: "4", display: "Ajmal", designation:"Ast. Manager" },
]
You can use filter in es5 or native js to substract two array object.
//Find data that are in arrayObjOne but not in arrayObjTwo
var uniqueResultArrayObjOne = arrayObjOne.filter(function(objOne) {
return !arrayObjTwo.some(function(objTwo) {
return objOne.userId == objTwo.empId;
});
});
In ES6 you can use Arrow function with Object destructuring of ES6.
const ResultArrayObjOne = arrayObjOne.filter(({ userId: userId }) => !arrayObjTwo.some(({ empId: empId }) => empId === userId));
console.log(ResultArrayObjOne);
You can create an object with keys as the unique value corresponding for each object in array and then filter each array based on existence of the key in other's object. It reduces the complexity of the operation.
ES6
let a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"}, { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}];
let b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}];
let valuesA = a.reduce((a,{value}) => Object.assign(a, {[value]:value}), {});
let valuesB = b.reduce((a,{value}) => Object.assign(a, {[value]:value}), {});
let result = [...a.filter(({value}) => !valuesB[value]), ...b.filter(({value}) => !valuesA[value])];
console.log(result);
ES5
var a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"}, { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}];
var b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}];
var valuesA = a.reduce(function(a,c){a[c.value] = c.value; return a; }, {});
var valuesB = b.reduce(function(a,c){a[c.value] = c.value; return a; }, {});
var result = a.filter(function(c){ return !valuesB[c.value]}).concat(b.filter(function(c){ return !valuesA[c.value]}));
console.log(result);
I found this solution using filter and some.
resultFilter = (firstArray, secondArray) => {
return firstArray.filter(firstArrayItem =>
!secondArray.some(
secondArrayItem => firstArrayItem._user === secondArrayItem._user
)
);
};
I think the #Cerbrus solution is spot on. I have implemented the same solution but extracted the repeated code into it's own function (DRY).
function filterByDifference(array1, array2, compareField) {
var onlyInA = differenceInFirstArray(array1, array2, compareField);
var onlyInb = differenceInFirstArray(array2, array1, compareField);
return onlyInA.concat(onlyInb);
}
function differenceInFirstArray(array1, array2, compareField) {
return array1.filter(function (current) {
return array2.filter(function (current_b) {
return current_b[compareField] === current[compareField];
}).length == 0;
});
}
you can do diff a on b and diff b on a, then merge both results
let a = [
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
{ value: "4", display: "Ryan" }
]
let b = [
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" }
]
// b diff a
let resultA = b.filter(elm => !a.map(elm => JSON.stringify(elm)).includes(JSON.stringify(elm)));
// a diff b
let resultB = a.filter(elm => !b.map(elm => JSON.stringify(elm)).includes(JSON.stringify(elm)));
// show merge
console.log([...resultA, ...resultB]);
let obj1 =[
{ id: 1, submenu_name: 'login' },
{ id: 2, submenu_name: 'Profile',},
{ id: 3, submenu_name: 'password', },
{ id: 4, submenu_name: 'reset',}
] ;
let obj2 =[
{ id: 2},
{ id: 3 },
] ;
// Need Similar obj
const result1 = obj1.filter(function(o1){
return obj2.some(function(o2){
return o1.id == o2.id; // id is unnique both array object
});
});
console.log(result1);
// Need differnt obj
const result2 = obj1.filter(function(o1){
return !obj2.some(function(o2){ // for diffrent we use NOT (!) befor obj2 here
return o1.id == o2.id; // id is unnique both array object
});
});
console.log(result2);
JavaScript has Maps, that provide O(1) insertion and lookup time. Therefore this can be solved in O(n) (and not O(nĀ²) as all the other answers do). For that, it is necessary to generate a unique primitive (string / number) key for each object. One could JSON.stringify, but that's quite error prone as the order of elements could influence equality:
JSON.stringify({ a: 1, b: 2 }) !== JSON.stringify({ b: 2, a: 1 })
Therefore, I'd take a delimiter that does not appear in any of the values and compose a string manually:
const toHash = value => value.value + "#" + value.display;
Then a Map gets created. When an element exists already in the Map, it gets removed, otherwise it gets added. Therefore only the elements that are included odd times (meaning only once) remain. This will only work if the elements are unique in each array:
const entries = new Map();
for(const el of [...firstArray, ...secondArray]) {
const key = toHash(el);
if(entries.has(key)) {
entries.delete(key);
} else {
entries.set(key, el);
}
}
const result = [...entries.values()];
const firstArray = [
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
{ value: "4", display: "Ryan" }
]
const secondArray = [
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
];
const toHash = value => value.value + "#" + value.display;
const entries = new Map();
for(const el of [...firstArray, ...secondArray]) {
const key = toHash(el);
if(entries.has(key)) {
entries.delete(key);
} else {
entries.set(key, el);
}
}
const result = [...entries.values()];
console.log(result);
Most of the observed code does not examine the whole object and only compares the value of a particular method. This solution is the same, except that you can specify that method yourself.
Here is an example:
const arr1 = [
{
id: 1,
name: "Tom",
scores: {
math: 80,
science: 100
}
},
{
id: 2,
name: "John",
scores: {
math: 50,
science: 70
}
}
];
const arr2 = [
{
id: 1,
name: "Tom",
scores: {
math: 80,
science: 70
}
}
];
function getDifference(array1, array2, attr) {
return array1.filter(object1 => {
return !array2.some(object2 => {
return eval("object1." + attr + " == object2." + attr);
});
});
}
// šŸ‘‡ļø [{id: 2, name: 'John'...
console.log(getDifference(arr1, arr2, "id"));
// šŸ‘‡ļø [{id: 2, name: 'John'...
console.log(getDifference(arr1, arr2, "scores.math"));
// šŸ‘‡ļø [{id: 1, name: 'Tom'...
console.log(getDifference(arr1, arr2, "scores.science"));
Most of answers here are rather complex, but isn't logic behind this quite simple?
check which array is longer and provide it as first parameter (if length is equal, parameters order doesnt matter)
Iterate over array1.
For current iteration element of array1 check if it is present in array2
If it is NOT present, than
Push it to 'difference' array
const getArraysDifference = (longerArray, array2) => {
const difference = [];
longerArray.forEach(el1 => { /*1*/
el1IsPresentInArr2 = array2.some(el2 => el2.value === el1.value); /*2*/
if (!el1IsPresentInArr2) { /*3*/
difference.push(el1); /*4*/
}
});
return difference;
}
O(n^2) complexity.
I prefer map object when it comes to big arrays.
// create tow arrays
array1 = Array.from({length: 400},() => ({value:Math.floor(Math.random() * 4000)}))
array2 = Array.from({length: 400},() => ({value:Math.floor(Math.random() * 4000)}))
// calc diff with some function
console.time('diff with some');
results = array2.filter(({ value: id1 }) => array1.some(({ value: id2 }) => id2 === id1));
console.log('diff results ',results.length)
console.timeEnd('diff with some');
// calc diff with map object
console.time('diff with map');
array1Map = {};
for(const item1 of array1){
array1Map[item1.value] = true;
}
results = array2.filter(({ value: id2 }) => array1Map[id2]);
console.log('map results ',results.length)
console.timeEnd('diff with map');
Having:
const array = [{id:3, name:'xx'} , {id:7, name:'yy'}, {id:9, name:'zz'}];
const array2 =[3,4,5];//These are a group of ids
I made a function that removes the objects from array that matches de ids within array2, like this:
export const aFilter = (array, array2) => {
array2.forEach(element => {
array = array.filter(item=> item.id !== element);
});
return array;
}
After calling the function we should have the array with no object wit id = 3
const rta = aFilter(array, array2);
//rta should be = [{id:7, name:'yy'}, {id:9, name:'zz'}];
It worked for me, and was pretty easy
I've made a generalized diff that compare 2 objects of any kind and can run a modification handler
gist.github.com/bortunac "diff.js"
an ex of using :
old_obj={a:1,b:2,c:[1,2]}
now_obj={a:2 , c:[1,3,5],d:55}
so property a is modified, b is deleted, c modified, d is added
var handler=function(type,pointer){
console.log(type,pointer,this.old.point(pointer)," | ",this.now.point(pointer));
}
now use like
df=new diff();
df.analize(now_obj,old_obj);
df.react(handler);
the console will show
mdf ["a"] 1 | 2
mdf ["c", "1"] 2 | 3
add ["c", "2"] undefined | 5
add ["d"] undefined | 55
del ["b"] 2 | undefined
Most generic and simple way:
findObject(listOfObjects, objectToSearch) {
let found = false, matchingKeys = 0;
for(let object of listOfObjects) {
found = false;
matchingKeys = 0;
for(let key of Object.keys(object)) {
if(object[key]==objectToSearch[key]) matchingKeys++;
}
if(matchingKeys==Object.keys(object).length) {
found = true;
break;
}
}
return found;
}
get_removed_list_of_objects(old_array, new_array) {
// console.log('old:',old_array);
// console.log('new:',new_array);
let foundList = [];
for(let object of old_array) {
if(!this.findObject(new_array, object)) foundList.push(object);
}
return foundList;
}
get_added_list_of_objects(old_array, new_array) {
let foundList = [];
for(let object of new_array) {
if(!this.findObject(old_array, object)) foundList.push(object);
}
return foundList;
}
I came across this question while searching for a way to pick out the first item in one array that does not match any of the values in another array and managed to sort it out eventually with array.find() and array.filter() like this
var carList= ['mercedes', 'lamborghini', 'bmw', 'honda', 'chrysler'];
var declinedOptions = ['mercedes', 'lamborghini'];
const nextOption = carList.find(car=>{
const duplicate = declinedOptions.filter(declined=> {
return declined === car
})
console.log('duplicate:',duplicate) //should list out each declined option
if(duplicate.length === 0){//if theres no duplicate, thats the nextOption
return car
}
})
console.log('nextOption:', nextOption);
//expected outputs
//duplicate: mercedes
//duplicate: lamborghini
//duplicate: []
//nextOption: bmw
if you need to keep fetching an updated list before cross-checking for the next best option this should work well enough :)
#atheane response : fork :
const newList = [
{ value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer" },
{ value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed" },
{ value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi2" },
{ value: "a63a6f77-c637-454e-abf2-dfb9b543af6c", display: "Ryan" },
];
const oldList = [
{ value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer"},
{ value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed"},
{ value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi"},
{ value: "e97339e1-939d-47ab-974c-1b68c9cfb536", display: "Ajmal"},
];
const resultsAdd = newList.filter(({ value: id1 }) => !oldList.some(({ value: id2 }) => id2 === id1));
const resultsRemove = oldList.filter(({ value: id1 }) => !newList.some(({ value: id2 }) => id2 === id1));
const resultsUpdate = newList.filter(({ value: id1, ...rest1 }) => oldList.some(({ value: id2, ...rest2 }) => id2 === id1 && JSON.stringify(rest1) !== JSON.stringify(rest2)));
console.log("added", resultsAdd);
console.log("removed", resultsRemove);
console.log("updated", resultsUpdate);
Most simple way could be use of filter and some together
Please refer below link
DifferenceInTwoArrayOfObjectInSimpleWay
If you are willing to use external libraries, You can use _.difference in underscore.js to achieve this. _.difference returns the values from array that are not present in the other arrays.
_.difference([1,2,3,4,5][1,4,10])
==>[2,3,5]

Find difference between two arrays

I have following Plunkr which works perfectly.
https://plnkr.co/edit/WDjoEK7bAVpKSJbAmB9D?p=preview
It uses the _.differenceWith() function of lodash, in order two save all array values, which are not contained by the two arrays.
var result = _.differenceWith(data, test, _.isEqual);
Now I have two problems:
1.) In our project we use an older Lodash Version where the function differenceWith is not implemented
2.) I only need to compare one value of the array. This currently compares the complete objects. I only need to compare the id property.
This will find the objects in arr1 that are not in arr2 based on the id attribute.
var arr1 = [ { "id": "1" }, { "id": "2" }, { "id": "3" } ];
var arr2 = [ { "id": "1" }, { "id": "2" } ];
var result = arr1.filter(o1 => arr2.filter(o2 => o2.id === o1.id).length === 0);
console.log(result);
Note that this example does not require lodash.
If you want to use a different comparison instead of id, you can change the o2.id === o1.id part to a different property.
Here is a more generic solution:
var arr1 = [ { "name": "a" }, { "name": "b" }, { "name": "c" } ];
var arr2 = [ { "name": "a" }, { "name": "c" } ];
function differenceWith(a1, a2, prop) {
return a1.filter(o1 => a2.filter(o2 => o2[prop] === o1[prop]).length === 0);
}
var result = differenceWith(arr1, arr2, 'name');
console.log(result);

How to get the difference between two arrays of objects in JavaScript

I have two result sets like this:
// Result 1
[
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
{ value: "4", display: "Ryan" }
]
// Result 2
[
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
]
The final result I need is the difference between these arrays ā€“ the final result should be like this:
[{ value: "4", display: "Ryan" }]
Is it possible to do something like this in JavaScript?
Using only native JS, something like this will work:
const a = [{ value:"0", display:"Jamsheer" }, { value:"1", display:"Muhammed" }, { value:"2", display:"Ravi" }, { value:"3", display:"Ajmal" }, { value:"4", display:"Ryan" }];
const b = [{ value:"0", display:"Jamsheer", $$hashKey:"008" }, { value:"1", display:"Muhammed", $$hashKey:"009" }, { value:"2", display:"Ravi", $$hashKey:"00A" }, { value:"3", display:"Ajmal", $$hashKey:"00B" }];
// A comparer used to determine if two entries are equal.
const isSameUser = (a, b) => a.value === b.value && a.display === b.display;
// Get items that only occur in the left array,
// using the compareFunction to determine equality.
const onlyInLeft = (left, right, compareFunction) =>
left.filter(leftValue =>
!right.some(rightValue =>
compareFunction(leftValue, rightValue)));
const onlyInA = onlyInLeft(a, b, isSameUser);
const onlyInB = onlyInLeft(b, a, isSameUser);
const result = [...onlyInA, ...onlyInB];
console.log(result);
For those who like one-liner solutions in ES6, something like this:
const arrayOne = [
{ value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer" },
{ value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed" },
{ value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi" },
{ value: "e97339e1-939d-47ab-974c-1b68c9cfb536", display: "Ajmal" },
{ value: "a63a6f77-c637-454e-abf2-dfb9b543af6c", display: "Ryan" },
];
const arrayTwo = [
{ value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer"},
{ value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed"},
{ value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi"},
{ value: "e97339e1-939d-47ab-974c-1b68c9cfb536", display: "Ajmal"},
];
const results = arrayOne.filter(({ value: id1 }) => !arrayTwo.some(({ value: id2 }) => id2 === id1));
console.log(results);
You could use Array.prototype.filter() in combination with Array.prototype.some().
Here is an example (assuming your arrays are stored in the variables result1 and result2):
//Find values that are in result1 but not in result2
var uniqueResultOne = result1.filter(function(obj) {
return !result2.some(function(obj2) {
return obj.value == obj2.value;
});
});
//Find values that are in result2 but not in result1
var uniqueResultTwo = result2.filter(function(obj) {
return !result1.some(function(obj2) {
return obj.value == obj2.value;
});
});
//Combine the two arrays of unique entries
var result = uniqueResultOne.concat(uniqueResultTwo);
import differenceBy from 'lodash/differenceBy'
const myDifferences = differenceBy(Result1, Result2, 'value')
This will return the difference between two arrays of objects, using the key value to compare them. Note two things with the same value will not be returned, as the other keys are ignored.
This is a part of lodash.
I take a slightly more general-purpose approach, although similar in ideas to the approaches of both #Cerbrus and #Kasper Moerch. I create a function that accepts a predicate to determine if two objects are equal (here we ignore the $$hashKey property, but it could be anything) and return a function which calculates the symmetric difference of two lists based on that predicate:
a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"}, { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}]
b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}]
var makeSymmDiffFunc = (function() {
var contains = function(pred, a, list) {
var idx = -1, len = list.length;
while (++idx < len) {if (pred(a, list[idx])) {return true;}}
return false;
};
var complement = function(pred, a, b) {
return a.filter(function(elem) {return !contains(pred, elem, b);});
};
return function(pred) {
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
};
}());
var myDiff = makeSymmDiffFunc(function(x, y) {
return x.value === y.value && x.display === y.display;
});
var result = myDiff(a, b); //=> {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}
It has one minor advantage over Cerebrus's approach (as does Kasper Moerch's approach) in that it escapes early; if it finds a match, it doesn't bother checking the rest of the list. If I had a curry function handy, I would do this a little differently, but this works fine.
Explanation
A comment asked for a more detailed explanation for beginners. Here's an attempt.
We pass the following function to makeSymmDiffFunc:
function(x, y) {
return x.value === y.value && x.display === y.display;
}
This function is how we decide that two objects are equal. Like all functions that return true or false, it can be called a "predicate function", but that's just terminology. The main point is that makeSymmDiffFunc is configured with a function that accepts two objects and returns true if we consider them equal, false if we don't.
Using that, makeSymmDiffFunc (read "make symmetric difference function") returns us a new function:
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
This is the function we will actually use. We pass it two lists and it finds the elements in the first not in the second, then those in the second not in the first and combine these two lists.
Looking over it again, though, I could definitely have taken a cue from your code and simplified the main function quite a bit by using some:
var makeSymmDiffFunc = (function() {
var complement = function(pred, a, b) {
return a.filter(function(x) {
return !b.some(function(y) {return pred(x, y);});
});
};
return function(pred) {
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
};
}());
complement uses the predicate and returns the elements of its first list not in its second. This is simpler than my first pass with a separate contains function.
Finally, the main function is wrapped in an immediately invoked function expression (IIFE) to keep the internal complement function out of the global scope.
Update, a few years later
Now that ES2015 has become pretty well ubiquitous, I would suggest the same technique, with a lot less boilerplate:
const diffBy = (pred) => (a, b) => a.filter(x => !b.some(y => pred(x, y)))
const makeSymmDiffFunc = (pred) => (a, b) => diffBy(pred)(a, b).concat(diffBy(pred)(b, a))
const myDiff = makeSymmDiffFunc((x, y) => x.value === y.value && x.display === y.display)
const result = myDiff(a, b)
//=> {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}
In addition, say two object array with different key value
// Array Object 1
const arrayObjOne = [
{ userId: "1", display: "Jamsheer" },
{ userId: "2", display: "Muhammed" },
{ userId: "3", display: "Ravi" },
{ userId: "4", display: "Ajmal" },
{ userId: "5", display: "Ryan" }
]
// Array Object 2
const arrayObjTwo =[
{ empId: "1", display: "Jamsheer", designation:"Jr. Officer" },
{ empId: "2", display: "Muhammed", designation:"Jr. Officer" },
{ empId: "3", display: "Ravi", designation:"Sr. Officer" },
{ empId: "4", display: "Ajmal", designation:"Ast. Manager" },
]
You can use filter in es5 or native js to substract two array object.
//Find data that are in arrayObjOne but not in arrayObjTwo
var uniqueResultArrayObjOne = arrayObjOne.filter(function(objOne) {
return !arrayObjTwo.some(function(objTwo) {
return objOne.userId == objTwo.empId;
});
});
In ES6 you can use Arrow function with Object destructuring of ES6.
const ResultArrayObjOne = arrayObjOne.filter(({ userId: userId }) => !arrayObjTwo.some(({ empId: empId }) => empId === userId));
console.log(ResultArrayObjOne);
You can create an object with keys as the unique value corresponding for each object in array and then filter each array based on existence of the key in other's object. It reduces the complexity of the operation.
ES6
let a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"}, { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}];
let b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}];
let valuesA = a.reduce((a,{value}) => Object.assign(a, {[value]:value}), {});
let valuesB = b.reduce((a,{value}) => Object.assign(a, {[value]:value}), {});
let result = [...a.filter(({value}) => !valuesB[value]), ...b.filter(({value}) => !valuesA[value])];
console.log(result);
ES5
var a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"}, { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}];
var b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}];
var valuesA = a.reduce(function(a,c){a[c.value] = c.value; return a; }, {});
var valuesB = b.reduce(function(a,c){a[c.value] = c.value; return a; }, {});
var result = a.filter(function(c){ return !valuesB[c.value]}).concat(b.filter(function(c){ return !valuesA[c.value]}));
console.log(result);
I found this solution using filter and some.
resultFilter = (firstArray, secondArray) => {
return firstArray.filter(firstArrayItem =>
!secondArray.some(
secondArrayItem => firstArrayItem._user === secondArrayItem._user
)
);
};
I think the #Cerbrus solution is spot on. I have implemented the same solution but extracted the repeated code into it's own function (DRY).
function filterByDifference(array1, array2, compareField) {
var onlyInA = differenceInFirstArray(array1, array2, compareField);
var onlyInb = differenceInFirstArray(array2, array1, compareField);
return onlyInA.concat(onlyInb);
}
function differenceInFirstArray(array1, array2, compareField) {
return array1.filter(function (current) {
return array2.filter(function (current_b) {
return current_b[compareField] === current[compareField];
}).length == 0;
});
}
you can do diff a on b and diff b on a, then merge both results
let a = [
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
{ value: "4", display: "Ryan" }
]
let b = [
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" }
]
// b diff a
let resultA = b.filter(elm => !a.map(elm => JSON.stringify(elm)).includes(JSON.stringify(elm)));
// a diff b
let resultB = a.filter(elm => !b.map(elm => JSON.stringify(elm)).includes(JSON.stringify(elm)));
// show merge
console.log([...resultA, ...resultB]);
let obj1 =[
{ id: 1, submenu_name: 'login' },
{ id: 2, submenu_name: 'Profile',},
{ id: 3, submenu_name: 'password', },
{ id: 4, submenu_name: 'reset',}
] ;
let obj2 =[
{ id: 2},
{ id: 3 },
] ;
// Need Similar obj
const result1 = obj1.filter(function(o1){
return obj2.some(function(o2){
return o1.id == o2.id; // id is unnique both array object
});
});
console.log(result1);
// Need differnt obj
const result2 = obj1.filter(function(o1){
return !obj2.some(function(o2){ // for diffrent we use NOT (!) befor obj2 here
return o1.id == o2.id; // id is unnique both array object
});
});
console.log(result2);
JavaScript has Maps, that provide O(1) insertion and lookup time. Therefore this can be solved in O(n) (and not O(nĀ²) as all the other answers do). For that, it is necessary to generate a unique primitive (string / number) key for each object. One could JSON.stringify, but that's quite error prone as the order of elements could influence equality:
JSON.stringify({ a: 1, b: 2 }) !== JSON.stringify({ b: 2, a: 1 })
Therefore, I'd take a delimiter that does not appear in any of the values and compose a string manually:
const toHash = value => value.value + "#" + value.display;
Then a Map gets created. When an element exists already in the Map, it gets removed, otherwise it gets added. Therefore only the elements that are included odd times (meaning only once) remain. This will only work if the elements are unique in each array:
const entries = new Map();
for(const el of [...firstArray, ...secondArray]) {
const key = toHash(el);
if(entries.has(key)) {
entries.delete(key);
} else {
entries.set(key, el);
}
}
const result = [...entries.values()];
const firstArray = [
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
{ value: "4", display: "Ryan" }
]
const secondArray = [
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
];
const toHash = value => value.value + "#" + value.display;
const entries = new Map();
for(const el of [...firstArray, ...secondArray]) {
const key = toHash(el);
if(entries.has(key)) {
entries.delete(key);
} else {
entries.set(key, el);
}
}
const result = [...entries.values()];
console.log(result);
Most of the observed code does not examine the whole object and only compares the value of a particular method. This solution is the same, except that you can specify that method yourself.
Here is an example:
const arr1 = [
{
id: 1,
name: "Tom",
scores: {
math: 80,
science: 100
}
},
{
id: 2,
name: "John",
scores: {
math: 50,
science: 70
}
}
];
const arr2 = [
{
id: 1,
name: "Tom",
scores: {
math: 80,
science: 70
}
}
];
function getDifference(array1, array2, attr) {
return array1.filter(object1 => {
return !array2.some(object2 => {
return eval("object1." + attr + " == object2." + attr);
});
});
}
// šŸ‘‡ļø [{id: 2, name: 'John'...
console.log(getDifference(arr1, arr2, "id"));
// šŸ‘‡ļø [{id: 2, name: 'John'...
console.log(getDifference(arr1, arr2, "scores.math"));
// šŸ‘‡ļø [{id: 1, name: 'Tom'...
console.log(getDifference(arr1, arr2, "scores.science"));
Most of answers here are rather complex, but isn't logic behind this quite simple?
check which array is longer and provide it as first parameter (if length is equal, parameters order doesnt matter)
Iterate over array1.
For current iteration element of array1 check if it is present in array2
If it is NOT present, than
Push it to 'difference' array
const getArraysDifference = (longerArray, array2) => {
const difference = [];
longerArray.forEach(el1 => { /*1*/
el1IsPresentInArr2 = array2.some(el2 => el2.value === el1.value); /*2*/
if (!el1IsPresentInArr2) { /*3*/
difference.push(el1); /*4*/
}
});
return difference;
}
O(n^2) complexity.
I prefer map object when it comes to big arrays.
// create tow arrays
array1 = Array.from({length: 400},() => ({value:Math.floor(Math.random() * 4000)}))
array2 = Array.from({length: 400},() => ({value:Math.floor(Math.random() * 4000)}))
// calc diff with some function
console.time('diff with some');
results = array2.filter(({ value: id1 }) => array1.some(({ value: id2 }) => id2 === id1));
console.log('diff results ',results.length)
console.timeEnd('diff with some');
// calc diff with map object
console.time('diff with map');
array1Map = {};
for(const item1 of array1){
array1Map[item1.value] = true;
}
results = array2.filter(({ value: id2 }) => array1Map[id2]);
console.log('map results ',results.length)
console.timeEnd('diff with map');
Having:
const array = [{id:3, name:'xx'} , {id:7, name:'yy'}, {id:9, name:'zz'}];
const array2 =[3,4,5];//These are a group of ids
I made a function that removes the objects from array that matches de ids within array2, like this:
export const aFilter = (array, array2) => {
array2.forEach(element => {
array = array.filter(item=> item.id !== element);
});
return array;
}
After calling the function we should have the array with no object wit id = 3
const rta = aFilter(array, array2);
//rta should be = [{id:7, name:'yy'}, {id:9, name:'zz'}];
It worked for me, and was pretty easy
I've made a generalized diff that compare 2 objects of any kind and can run a modification handler
gist.github.com/bortunac "diff.js"
an ex of using :
old_obj={a:1,b:2,c:[1,2]}
now_obj={a:2 , c:[1,3,5],d:55}
so property a is modified, b is deleted, c modified, d is added
var handler=function(type,pointer){
console.log(type,pointer,this.old.point(pointer)," | ",this.now.point(pointer));
}
now use like
df=new diff();
df.analize(now_obj,old_obj);
df.react(handler);
the console will show
mdf ["a"] 1 | 2
mdf ["c", "1"] 2 | 3
add ["c", "2"] undefined | 5
add ["d"] undefined | 55
del ["b"] 2 | undefined
Most generic and simple way:
findObject(listOfObjects, objectToSearch) {
let found = false, matchingKeys = 0;
for(let object of listOfObjects) {
found = false;
matchingKeys = 0;
for(let key of Object.keys(object)) {
if(object[key]==objectToSearch[key]) matchingKeys++;
}
if(matchingKeys==Object.keys(object).length) {
found = true;
break;
}
}
return found;
}
get_removed_list_of_objects(old_array, new_array) {
// console.log('old:',old_array);
// console.log('new:',new_array);
let foundList = [];
for(let object of old_array) {
if(!this.findObject(new_array, object)) foundList.push(object);
}
return foundList;
}
get_added_list_of_objects(old_array, new_array) {
let foundList = [];
for(let object of new_array) {
if(!this.findObject(old_array, object)) foundList.push(object);
}
return foundList;
}
I came across this question while searching for a way to pick out the first item in one array that does not match any of the values in another array and managed to sort it out eventually with array.find() and array.filter() like this
var carList= ['mercedes', 'lamborghini', 'bmw', 'honda', 'chrysler'];
var declinedOptions = ['mercedes', 'lamborghini'];
const nextOption = carList.find(car=>{
const duplicate = declinedOptions.filter(declined=> {
return declined === car
})
console.log('duplicate:',duplicate) //should list out each declined option
if(duplicate.length === 0){//if theres no duplicate, thats the nextOption
return car
}
})
console.log('nextOption:', nextOption);
//expected outputs
//duplicate: mercedes
//duplicate: lamborghini
//duplicate: []
//nextOption: bmw
if you need to keep fetching an updated list before cross-checking for the next best option this should work well enough :)
#atheane response : fork :
const newList = [
{ value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer" },
{ value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed" },
{ value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi2" },
{ value: "a63a6f77-c637-454e-abf2-dfb9b543af6c", display: "Ryan" },
];
const oldList = [
{ value: "4a55eff3-1e0d-4a81-9105-3ddd7521d642", display: "Jamsheer"},
{ value: "644838b3-604d-4899-8b78-09e4799f586f", display: "Muhammed"},
{ value: "b6ee537a-375c-45bd-b9d4-4dd84a75041d", display: "Ravi"},
{ value: "e97339e1-939d-47ab-974c-1b68c9cfb536", display: "Ajmal"},
];
const resultsAdd = newList.filter(({ value: id1 }) => !oldList.some(({ value: id2 }) => id2 === id1));
const resultsRemove = oldList.filter(({ value: id1 }) => !newList.some(({ value: id2 }) => id2 === id1));
const resultsUpdate = newList.filter(({ value: id1, ...rest1 }) => oldList.some(({ value: id2, ...rest2 }) => id2 === id1 && JSON.stringify(rest1) !== JSON.stringify(rest2)));
console.log("added", resultsAdd);
console.log("removed", resultsRemove);
console.log("updated", resultsUpdate);
Most simple way could be use of filter and some together
Please refer below link
DifferenceInTwoArrayOfObjectInSimpleWay
If you are willing to use external libraries, You can use _.difference in underscore.js to achieve this. _.difference returns the values from array that are not present in the other arrays.
_.difference([1,2,3,4,5][1,4,10])
==>[2,3,5]

Categories