I'm trying to display the name of property where their values are difference.
Then, I'm trying to display the property which is not present on the other variable
myObj1 = {
"name": "John",
"age": "45",
"car": 20,
"test": 30,
"example": 20
};
myObj2 = {
"name": "John",
"age": "30",
"car": 10,
"example": 10
};
// or
//myObj1 = { "name":"John", "age":"45", "car":20 };
//myObj2 = { "name":"John", "age":"30", "car":10,"test":30 };
// find keys
keyObj1 = Object.keys(myObj1);
keyObj2 = Object.keys(myObj2);
// find values
valueObj1 = Object.values(myObj1);
valueObj2 = Object.values(myObj2);
// find max length to iterate
if (keyObj1.length > keyObj2.length) {
var biggestKey = keyObj1.length;
} else {
var biggestKey = keyObj2.length;
}
// now compare their keys and values
for (var i = 0; i < biggestKey; i++) {
//console.log(biggestKey)
if (keyObj1[i] == keyObj2[i] && valueObj1[i] !== valueObj2[i]) {
console.log('property:' + keyObj1[i]);
console.log('first:' + valueObj1[i]);
console.log('second:' + valueObj2[i]);
}
}
Actual result:
property: age, 45,30
property: car,20,10
property: test,30,10
property: example,20,undefined
Expected result:
property: age, 45,30
property: car,20,10
property: test,30,undefined
property: example,20,10
Problems
biggestKey is a length instead of array
compare object by key in biggestKey
myObj1 = {
"name": "John",
"age": "45",
"car": 20,
"test": 30,
"example": 20
};
myObj2 = {
"name": "John",
"age": "30",
"car": 10,
"example": 10
};
// find keys
keyObj1 = Object.keys(myObj1);
keyObj2 = Object.keys(myObj2);
// find max length to iterate
if (keyObj1.length > keyObj2.length) {
var biggestKey = keyObj1;
} else {
var biggestKey = keyObj2;
}
// now compare their keys and values
for (var i = 0; i < biggestKey.length; i++) {
//console.log(biggestKey)
var key = biggestKey[i];
if (myObj1[key] != myObj2[key]) {
console.log('project:', key, myObj1[key], myObj2[key]);
}
}
Hope it will help you
function getDifference(compareObject, baseObject) {
function difference(compareObject, baseObject) {
return _.transform(compareObject, function(results, value, key) {
if (!_.isEqual(value, baseObject[key])) {
results[key] = (_.isObject(value) && _.isObject(baseObject[key])) ? changes(value, baseObject[key]) : value;
}
});
}
return difference(compareObject, baseObject);
}
The trick is to iterate through both objects and to ignore the properties that exist in both objects in the second loop.
var myObj1 = {
"name": "John",
"age": "45",
"car": 20,
"test": 30,
"example": 20
};
var myObj2 = {
"name": "John",
"age": "30",
"car": 10,
"example": 10
};
for (var key in myObj1) {
if (myObj1[key] !== myObj2[key]) console.log("property:", key, myObj1[key], myObj2[key]);
}
for (key in myObj2) {
if (!(key in myObj2)) { // ignore if key exists in myObj1 (if it exists, then it got checked in the previous loop)
if (myObj1[key] !== myObj2[key]) console.log("property:", key, myObj1[key], myObj2[key]);
}
}
Related
const obj =
[
{
"id":"1",
"name":"a",
"email":"abc#gmail.com",
"expiryType":"premium"
},
{
"id":"2",
"name":"b",
"email":"abc#gmail.com",
"expiryType":"gold"
},
{
"id":"3",
"name":"b",
"email":"test#gmail.com",
"expiryType":"premium"
},
]
can somebody please help me how to filter out objects where email is same but i want to keep the one with expiry Type is premium ? How to achieve this using Javascript
Expected output would be
const obj =
[
{
"id":"1",
"name":"a",
"email":"abc#gmail.com",
"expiryType":"premium"
},
{
"id":"3",
"name":"b",
"email":"test#gmail.com",
"expiryType":"premium"
},
]
Assuming you want to keep the latest year's entry, you can keep a Map of the email addresses and years you've seen. See comments:
// The new list
const filtered = [];
// Known emails
const known = new Map();
// Loop through...
for (const entry of obj) {
// Get this email and expiry
const {email, expiryYear} = entry;
// Get the previous info if any
const previous = known.get(email);
if (previous) {
// If the previous one is older than this one,
// replace it with this one
if (previous.expiryYear < expiryYear) {
filtered[previous.index] = entry;
}
} else {
// Add this to the known list and the filtered array
known.set(email, {
index: filtered.length,
expiryYear
});
filtered.push(entry);
}
}
const obj = [
{
"id":"1",
"name":"a",
"email":"abc#gmail.com",
"expiryYear":"2020"
},
{
"id":"2",
"name":"a",
"email":"abc#gmail.com",
"expiryYear":"2019"
},
{
"id":"3",
"name":"b",
"email":"test#gmail.com",
"expiryYear":"2020"
},
];
// The new list
const filtered = [];
// Known emails
const known = new Map();
// Loop through...
for (const entry of obj) {
// Get this email and expiry
const {email, expiryYear} = entry;
// Get the previous info if any
const previous = known.get(email);
if (previous) {
// If the previous one is older than this one,
// replace it with this one
if (previous.expiryYear < expiryYear) {
filtered[previous.index] = entry;
}
} else {
// Add this to the known list and the filtered array
known.set(email, {
index: filtered.length,
expiryYear
});
filtered.push(entry);
}
}
console.log(filtered);
This has the advantage of not constantly re-scanning the new list for known entries.
You can filter out whole object based on unique key you want as below.
const obj =
[
{
"id": "1",
"name": "a",
"email": "abc#gmail.com",
"expiryType": "premium"
},
{
"id": "2",
"name": "b",
"email": "abc#gmail.com",
"expiryType": "gold"
},
{
"id": "3",
"name": "b",
"email": "test#gmail.com",
"expiryType": "premium"
}
]
function arrayUnique(arr, uniqueKey) {
const flagList = []
return arr.filter(function(item) {
if (flagList.findIndex(flagItem => flagItem[uniqueKey] === item[uniqueKey]) === -1) {
flagList.push(item)
return true
}
})
}
Method Calling....
let newObj = arrayUnique(obj,'email')
Output:
newObj = [
{
"id": "1",
"name": "a",
"email": "abc#gmail.com",
"expiryType": "premium"
},
{
"id": "3",
"name": "b",
"email": "test#gmail.com",
"expiryType": "premium"
}
]
Hope this helps.
You can do it simply with 2 loops. Maybe not the fastes but the simplest:
function deleteDouble(array, objectKey) {
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < array.length; j++) {
if (i == j) {
continue;
}
if (array[i][objectKey] == array[j][objectKey]) {
array.splice(i, 1);
i = 0;
j = 0;
break;
}
}
}
return array;
}
deleteDouble(obj, "email");
This is a two part question that I can't seem to solve. Part one requires that the entire object belonging to 'Theo' is removed somehow. Part two needs the object changed by editing one of the properties values belonging to 'Lorie'. Here's the array and instructions:
var employees = [{
"firstName": "Von",
"lastName": "Budibent",
"email": "vbudibent0#163.com",
"department": "Sales"
}, {
"firstName": "Catherina",
"lastName": "Swalowe",
"email": "cswalowe1#example.com",
"department": "Engineering"
}, {
"firstName": "Theo",
"lastName": "Trill",
"email": "ttrill2#sina.com.cn",
"department": "Services"
}, {
"firstName": "Elsy",
"lastName": "McCrorie",
"email": "emccrorie3#netscape.com",
"department": "Legal"
}, {
"firstName": "Lorie",
"lastName": "Handsheart",
"email": "lhandsheart4#fotki.com",
"department": "Research and Development"
}]
/* Create a function called 'employeeUpdater'. employeeUpdater will loop
over the array above and perform the following:
1. If employee's first name is Theo, remove that employee because he just
got fired.
2. If the employee's first name is Lorie, change her department to 'HR'.
3. Return the updated employee array. */
All I have to start is the following:
var employeeUpdater = () => {
for (let i = 0; i < employees.length; i++) {
if (employees[i] = 'Theo') {
employees.remove(employees[i]);
} else if (employees[i] = 'Lorie') {
employees.department = 'HR';
}
} return employees;
}
Something is wrong with the code
Javascript arrays don't have an method with name remove, instead you need to use Array#splice method for removing an item. But I can suggest this solution.
First use Array#filter to exclude the objects with name Theo then use Array#map or Array#forEach to iterate over the arrays an find the objects which name with Lorie and change it's department a.
var employees = [{
"firstName": "Von",
"lastName": "Budibent",
"email": "vbudibent0#163.com",
"department": "Sales"
}, {
"firstName": "Catherina",
"lastName": "Swalowe",
"email": "cswalowe1#example.com",
"department": "Engineering"
}, {
"firstName": "Theo",
"lastName": "Trill",
"email": "ttrill2#sina.com.cn",
"department": "Services"
}, {
"firstName": "Elsy",
"lastName": "McCrorie",
"email": "emccrorie3#netscape.com",
"department": "Legal"
}, {
"firstName": "Lorie",
"lastName": "Handsheart",
"email": "lhandsheart4#fotki.com",
"department": "Research and Development"
}];
var editedEmployees = employees
.filter(emp => emp.firstName !== 'Theo')
.map(emp =>
({
"firstName": emp.firstName,
"lastName": emp.lastName,
"email": emp.email,
"department": emp.firstName === 'Lorie' ? 'HR' : emp.department
}));
console.log(editedEmployees)
you can do it with splice():
var employeeUpdater = () => {
for (let i = 0; i < employees.length; i++) {
if (employees[i].firstName == 'Theo') {
employees.splice(i, 1);
i--;
} else if (employees[i].firstName == 'Lorie') {
employees[i].department = 'HR';
}
}
}return employees;
One of the tricky things about referencing objects in arrays is that you need to remember you have to reference them with the array index number and then the object name like employees[2].firstName would be how you reference Theo.
Also, the splice method is best for removing an array as stated above.
I believe the code you were trying to write would look like this:
var employeeUpdater = () => {
for (let i = 0; i < employees.length; i++) {
if (employees[i].firstName === 'Theo') {
employees.splice(i, 1);
} else if (employees[i].firstName === 'Lorie') {
employees[i].department = 'HR';
}
} return employees;
}
You should learn to program in an Object Oriented manner. Perhaps this will help:
//<![CDATA[
var pre = onload;
onload = function(){
if(pre)pre(); // change pre var name if using technique on other pages
var employees = [{
firstName:'Von',
lastName: 'Budibent',
email:'vbudibent0#163.com',
department:'Sales'
}, {
firstName:'Catherina',
lastName:'Swalowe',
email:'cswalowe1#example.com',
department:'Engineering'
}, {
firstName:'Theo',
lastName:'Trill',
email:'ttrill2#sina.com.cn',
department:'Services'
}, {
firstName:'Elsy',
lastName:'McCrorie',
email:'emccrorie3#netscape.com',
department:'Legal'
}, {
firstName:'Lorie',
lastName:'Handsheart',
email:'lhandsheart4#fotki.com',
department:'Research and Development'
}];
function EmployeeHandler(employeeArray){
this.employees = employeeArray;
this.removeByFirstName = function(firstName, caseSensitive){
var emp = this.employees;
var rx = caseSensitive ? new RegExp(firstName) : new RegExp(firstName, 'i');
for(var i=0,l=emp.length; i<l; i++){
if(emp[i].firstName.match(rx)){
this.employees.splice(i, 1);
return this;
}
}
return false;
}
this.removeByLastName = function(lastName, caseSensitive){
var emp = this.employees;
var rx = caseSensitive ? new RegExp(lastName) : new RegExp(lastName, 'i');
for(var i=0,l=emp.length; i<l; i++){
if(emp[i].lastName.match(rx)){
this.employees.splice(i, 1);
return this;
}
}
return false;
}
this.getByFirstName = function(firstName, caseSensitive){
var emp = this.employees;
var rx = caseSensitive ? new RegExp(firstName) : new RegExp(firstName, 'i');
for(var i=0,l=emp.length,em; i<l; i++){
em = emp[i];
if(em.firstName.match(rx)){
return em;
}
}
return false;
}
this.getByLastName = function(lastName, caseSensitive){
var emp = this.employees;
var rx = caseSensitive ? new RegExp(lastName) : new RegExp(lastName, 'i');
for(var i=0,l=emp.length,em; i<l; i++){
em = emp[i];
if(em.lastName.match(rx)){
return em;
}
}
return false;
}
}
var eh = new EmployeeHandler(employees);
var bb = eh.removeByFirstName('Theo').getByLastName('Budibent');
bb.department = 'Intelligent Design';
console.log(eh.employees); console.log(bb); console.log(eh.employees);
}
//]]>
Try this
var editedEmployees = employees
.filter(emp => emp.firstName !== 'Theo')
.map((emp) => {emp.department = emp.firstName === 'Lorie' ? 'HR' :
emp.department; return emp;});
If you like to work with lodash you can make your code easier to read.
So your script should become like this:
var _ = require('lodash');
/* Remove element */
_.remove(employees, function (employee) { return employee.firstName === 'Theo'; });
/* Get element to change */
var employee = _.find(employees,function (employee) { return employee.firstName === 'Lorie'; });
/* Change element */
employee.firstName = 'HR';
/* Right now employees store the right result */
I have this JSON structure:
[{
"name": "ankit",
"DOB": "23/06"
}, {
"name": "kapil",
"DOB": "26/06"
}, {
"name": "ankit",
"DOB": "27/06"
}]
I want to count similar object with value ankit. How can I do this?
You can use Array.prototype.filter():
var count = json.filter(function (el) {
return el.name == 'ankit';
}).length;
How about:
let a = [
{ "name": "ankit", "DOB": "23/06" },
{ "name": "kapil", "DOB": "26/06" },
{ "name": "ankit", "DOB": "27/06" }
];
let count = 0;
a.forEach(item => {
if (item.name === "ankit") {
count++;
}
});
(code in playground)
You could use an object for counting and get the wanted count for a name with the name as property.
var data = [{ "name": "ankit", "DOB": "23/06" }, { "name": "kapil", "DOB": "26/06" }, { "name": "ankit", "DOB": "27/06" }],
count = {};
data.forEach(function (a) {
count[a.name] = (count[a.name] || 0) + 1;
});
console.log(count);
console.log(count['ankit']);
You can use the reduce method to reduce the items that have the name ankit to a number.
var items = [
{
name: 'ankit',
DOB: '23/06'
},
{
name: 'kapil',
DOB: '26/06'
},
{
name: 'ankit',
DOB: '27/06'
}
]
var numItems = items.reduce(function (count, item) {
return item.name === 'ankit' ? count + 1 : count
}, 0)
document.write('Number of items with the name `ankit`: ' + numItems)
1. Get the object from JSON:
var obj = JSON.parse(text);
2. Get your array filtered:
var count = obj.filter(function(obj) { return obj.name == "ankit" }).length;
Below are my two arrays .I want to compare them and the resultant array should contain the updated values.Id's are common..
The arrays spans to n levels ie., there is no fixed levels..
The first array ie., the array before updation..
var parentArray1=[
{
"id": 1,
"name": "test",
"context": [
{
"id": 1.1,
"name": "test 1.1"
}
]
},
{
"id": 2,
"name": "test"
},
{
"id": 3,
"name": "test",
"context": [
{
"id": 3.1,
"name": "test 3.1"
}
]
},
{
"id": 4,
"name": "test"
}
]
The operations that i performed are
1.Adding a new Item
2.Updating an existing item
As a result of these two operations the changed values I will be getting in a different array..
ie.,
var changedArray=
[
{
"id": 1,
"name": "test1",
"context": [
{
"id": 1.1,
"name": "Changed test 1.1"
}
]
},
{
"id": 5,
"name": "test5"
}
]
Now I have written a generic function that loops through the parentArray1 and using the unique propertiesI need to either add a new item,if the item is there in the changedArray or update an existing item at any level
The resultant array should be ..
[
{
"id": 1,
"name": "test",
"context": [
{
"id": 1.1,
"name": "Changed test 1.1"
}
]
},
{
"id": 2,
"name": "test"
},
{
"id": 3,
"name": "test",
"context": [
{
"id": 3.1,
"name": "test 3.1"
}
]
},
{
"id": 4,
"name": "test"
},
{
"id": 5,
"name": "test5"
}
]
Generic function:
compareArray(parentArray1, changedArray, ["id"]);
function compareArray(array1, array2, propertyArray) {
var newItem = new Array();
array2.map(function(a1Item) {
array1.map(function(a2Item) {
/ If array loop again /
if (a2Item.constructor === Array) {
compareArray(a2Item, a1Item)
} else {
/ loop the property name to validate /
propertyArray.map(function(property) {
if (a2Item[property]) {
if (a2Item[property] === a1Item[property]) {
a2Item = a1Item
} else {
var isAvailable = _.find(newItem, function(item) {
return item[property] === a1Item[property]
})
if (!isAvailable) {
newItem.push(a1Item);
}
}
}
})
}
});
});
/ Insert the new item into the source array /
newItem.map(function(item) {
array1.push(item);
});
console.log("After Compare : " + array1);
}
I suggest to use a temporary object for the reference to the id and update if exist or push if not exist.
var parentArray1 = [{ "id": 1, "name": "test", "context": [{ "id": 1.1, "name": "test 1.1" }] }, { "id": 2, "name": "test" }, { "id": 3, "name": "test", "context": [{ "id": 3.1, "name": "test 3.1" }] }, { "id": 4, "name": "test" }],
changedArray = [{ "id": 1, "name": "test1", "context": [{ "id": 1.1, "name": "Changed test 1.1" }] }, { "id": 5, "name": "test5" }];
function insert(array, data) {
function iter(array) {
array.forEach(function (a) {
if (!('id' in a)) {
return;
}
if (o[a.id] !== a) {
o[a.id] = a;
}
Object.keys(a).forEach(function (k) {
Array.isArray(a[k]) && iter(a[k]);
});
});
}
var o = {};
iter(array);
data.forEach(function (a) {
if (o[a.id]) {
Object.keys(a).forEach(function (k) {
o[a.id][k] = a[k];
});
return;
}
array.push(a);
});
}
insert(parentArray1, changedArray);
document.write('<pre>' + JSON.stringify(parentArray1, 0, 4) + '</pre>');
This is what I came up with:
function sameKeys(o1, o2, keys) {
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!o1.hasOwnProperty(key) || !o2.hasOwnProperty(key))
throw 'compared objects do not have the key ' + key;
if (o1[key] !== o2[key])
return false;
}
return true;
}
function isNothing(o) {
return typeof(o) === 'undefined' || o === null;
}
// this does not work if objects have functions as properties
function clone(o) {
if (isNothing(o))
return o;
return JSON.parse(JSON.stringify(o));
}
function extend(o1, o2, keys) {
if (isNothing(o2))
return;
if (isNothing(o1))
throw ('first parameter cannot be empty');
if (typeof(o1) != 'object' || typeof(o2) != 'object')
throw ('extend only works on objects');
Object.keys(o2).forEach(function (key) {
var newVal = o2[key];
if (o1.hasOwnProperty(key)) {
if (isNothing(newVal)) {
delete o1[key];
} else
if (Array.isArray(newVal)) {
compareArray(o1[key], newVal, keys);
} else {
switch (typeof(newVal)) {
case 'object':
extend(o1[key], newVal, keys);
break;
case 'boolean':
case 'number':
case 'string':
o1[key] = newVal;
break;
default:
throw 'not supported property type: ' + typeof(newVal);
}
}
} else {
o1[key] = clone(newVal);
}
});
}
function removeFromArray(arr, ids, keyArray) {
var indexes = [];
var it1s = arr.forEach(function (it, idx) {
if (sameKeys(ids, it, keyArray)) {
indexes.push(idx);
} else {
Object.keys(it).forEach(function (key) {
var newVal = it[key];
if (Array.isArray(newVal)) {
removeFromArray(it[key], ids, keyArray);
}
});
}
});
if (indexes.length) {
if (indexes.length > 1)
throw 'found multiple possible objects for the same key combination'
arr.splice(indexes[0], 1);
}
}
function compareArray(a1, a2, keyArray) {
a2.forEach(function (it2) {
var it1s = a1.filter(function (it) {
return sameKeys(it2, it, keyArray);
});
var it1;
if (!it1s.length) {
it1 = clone(it2);
a1.push(it1);
} else {
if (it1s.length > 1)
throw 'found multiple possible objects for the same key combination'
it1 = it1s[0];
extend(it1, it2, keyArray);
}
if (it2.removedIds) {
it2.removedIds.forEach(function (ids) {
removeFromArray(a1, ids, keyArray);
});
}
});
}
Use it with compareArray(parentArray1,changedArray,['id']);
Note that it would not work with objects that contain functions. Also, if the arrays would be large, perhaps a better solution is to sort both arrays by key, then always look from the last found object up. That's all I got for now.
Updated it with some concepts from Nina and some clearing of the code.
As I understood it, you only want to add properties. So extend({a: {b: 2}},{a:{c:3}}) will result in {a: {b:2,c:3}}. If this is not what you wanted, let me know.
I also added functionality for removing ids. If any of the objects in the array contains a removedIds array of the form [{id: 4},{id: 5}] then the items with those ids will be removed from the original array.
Slight modification on code, to satisfy your conditions. Try it!
function compareArray(originalArray, destinationArray, propertyArray) {
var newItem = new Array(), processedItem = new Array();
for (var i = 0; i < originalArray.length; i++) {
var sourceElement = originalArray[i];
for (var j = 0; j < destinationArray.length; j++) {
var destinationElement = destinationArray[j];
var isUpdated = false;
if (sourceElement.constructor === Array) {
compareArray(sourceElement, destinationElement, propertyArray);
} else {
/* loop the property name to validate */
propertyArray.map(function(property) {
if (sourceElement[property]) {
if (sourceElement[property] === destinationElement[property]) {
originalArray[i] = _.clone(destinationElement);
isUpdated = true;
return;
} else {
var isAvailable = _.find(newItem, function(item) {
return item[property] === destinationElement[property];
});
if (!isAvailable) {
var isAlreadyProcessed = _.find(processedItem, function(item) {
return item[property] === destinationElement[property];
});
if(!isAlreadyProcessed){
newItem.push(destinationElement);
}
}
}
}
});
}
if (isUpdated === true) {
break;
}
}
processedItem.push(sourceElement);
}
newItem.map(function(item) {
originalArray.push(item);
});
return originalArray;
}
i'm trying to create a <String, Array()> map from a json object.
Imagine i got this json structure:
[
{
"userId": "123123",
"password": "fafafa",
"age": "21"
},
{
"userId": "321321",
"password": "nana123",
"age": "34"
}
]
The map i want to create would be:
key (string), value (array)
{
"userId": [
"123123",
"321321"
],
"password": [
"fafafa",
"nana123"
],
"age": [
"21",
"34"
]
}
Is it possible to do this? :/
Thanks in advance.
Demo
var json = '[{"userId" : "123123", "password": "fafafa", "age": "21"}, {"userId" : "321321", "password" : "nana123", "age" : "34"}]';
var list = JSON.parse(json);
var output = {};
for(var i=0; i<list.length; i++)
{
for(var key in list[i])
{
if(list[i].hasOwnProperty(key))
{
if(typeof output[key] == 'undefined')
{
output[key] = [];
}
output[key].push(list[i][key]);
}
}
}
document.write(JSON.stringify(output));
Outputs:
{"userId":["123123","321321"],"password":["fafafa","nana123"],"age":["21","34"]}
function mergeAttributes(arr) {
return arr.reduce(function(memo, obj) { // For each object in the input array.
Object.keys(obj).forEach(function(key) { // For each key in the object.
if (!(key in memo)) { memo[key] = []; } // Create an array the first time.
memo[key].push(obj[key]); // Add this property to the reduced object.
});
return memo;
}, {});
}
var json = '[{"userId" : "123123", "password": "fafafa", "age": "21"}, {"userId" : "321321", "password" : "nana123", "age" : "34"}]';
mergeAttributes(JSON.parse(json));
// {
// "userId": ["123123", "321321"],
// "password": ["fafafa", "nana123"],
// "age": ["21", "34"]
// }
Javascript's JSON.stringify will help you to convert any JSON compliant object model into a JSON string.