JavaScript (Lodash) - Deep comparison of two objects - javascript

Let's say I have two deep objects:
var oldData = {
"id": 1,
"first_name": "Eric",
"last_name": "Henry",
"info": {
"email": "ehenry0#smh.com.au",
"gender": "Male",
"ip_address": "7.11.169.150",
"age": 11
}
};
var newData = {
"id": 2,
"first_name": "Tommy",
"last_name": "Henry",
"info": {
"email": "tommy#ghenrry.com",
"gender": "Male",
"ip_address": "7.11.169.150",
"age": 15
}
};
How would I use lodash (or JavaScript) to traverse through each object and get the value of each different value, so in the top case it would be
[
{old: 1, new: 2},
{old: 'Eric', new: 'Tommy'},
{old: 'ehenry0#smh.com.au', new: 'tommy#ghenrry.com'},
{old: 11, new: 15},
]
Here is what I have so far:
var oldData = {
"id": 1,
"first_name": "Eric",
"last_name": "Henry",
"info": {
"email": "ehenry0#smh.com.au",
"gender": "Male",
"ip_address": "7.11.169.150",
"age": 11
}
};
var newData = {
"id": 2,
"first_name": "Tommy",
"last_name": "Henry",
"info": {
"email": "tommy#ghenrry.com",
"gender": "Male",
"ip_address": "7.11.169.150",
"age": 15
}
};
var diffObj = _.difference(_.keys(oldData), _.keys(newData));
console.log(JSON.stringify(diffObj, null, 4));
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>

The solution using custom recursive function compareUserData and Object.keys() function:
var oldData = { "id": 1, "first_name": "Eric", "last_name": "Henry", "info": { "email": "ehenry0#smh.com.au", "gender": "Male", "ip_address": "7.11.169.150", "age": 11 }
};
var newData = { "id": 2, "first_name": "Tommy", "last_name": "Henry", "info": { "email": "tommy#ghenrry.com", "gender": "Male", "ip_address": "7.11.169.150", "age": 15 }
};
function compareUserData(oldData, newData, result) {
Object.keys(oldData).forEach(function (k) {
if (typeof oldData[k] !== 'object') {
if (oldData[k] != newData[k]) this.push({'old': oldData[k], 'new': newData[k]});
} else {
compareUserData(oldData[k], newData[k], this);
}
}, result);
return result;
}
var result = compareUserData(oldData, newData, []);
console.log(result);

You may want to iterate through your objects properties, and check manually if something changed.
To see how you can iterate on properties : Iterate through object properties
EDIT : Your object has nested properties, read this post to see how you can check that too : How do I check if an object has a property in JavaScript?

Related

What is the best way to find if there are any duplicates in nested child property in a JavaScript Object?

I have an array of objects(Vue 3 prop) like below. The array is for room objects. Each room contains adults and childs array with adult and child objects. Now I need to mark the duplicate names (first and last name together) by adding a property name error (Shown in example).
[
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "John", "last": "Doe"},
{ "title": "Mrs.", "first": "Jane", "last": "Doe"}
],
"children": [
{ "title": "Ms.", "first": "Jane", "last": "Doe"},
{ "title": "Mr.", "first": "Joe", "last": "Doe" }
]
},
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "Johny", "last": "Doe",},
{ "title": "Mrs.", "first": "Jane", "last": "Doe",}
],
"children": [
{ "title": "Ms.", "first": "Jane", "last": "Doe"},
{ "title": "Mr.", "first": "Jui", "last": "Doe"}
]
},
]
After I run the function or code in question. The resulting array should look like below.
[
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "John", "last": "Doe"},
{ "title": "Mrs.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." }
],
"children": [
{ "title": "Ms.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." },
{ "title": "Mr.", "first": "Joe", "last": "Doe" }
]
},
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "Johny", "last": "Doe", },
{ "title": "Mrs.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." }
],
"children": [
{ "title": "Ms.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." },
{ "title": "Mr.", "first": "Jui", "last": "Doe" }
]
},
]
Update:
This is my first question to Stack Overflow, even though I am regular user of the platform for last 7+ years.
I am overwhelmed by the responses and definitely will go through each solution.
I am not a JS developer and tried to make a solution (inspired by
vanowm's comment) that now looks like below. I believe the responses have a better solution.
const isDuplicate = function (names, person) {
let result = false;
names.forEach(function (name) {
if(name.first === person.first && name.last === person.last){
result = true;
}
});
return result;
}
const validateNames = function () {
let names = [];
rooms.forEach(function (room) {
room.adults.forEach(function (adult) {
if (isDuplicate(names, adult)) {
adult.error = 'Duplicate name, please update.'
// I can do this because it is a Vue Reactive.
} else {
adult.error = ''
names.push(adult);
}
})
room.childs.forEach(function (child) {
if (isDuplicate(names, child)) {
child.error = 'Duplicate name, please update.'
} else {
child.error = ''
names.push(child);
}
})
});
};```
Here's my naive attempt
I assumed you want to find duplicates among adults separately from duplicates among children - it's not clear since the only duplicate is Jane Doe and she appears twice as an adult and twice as a child!
const data = [
{
RoomType: {},
Price: {},
Messages: [],
CancellationPolicyStatus: "",
adults: [
{ title: "Mr.", first: "John", last: "Doe" },
{ title: "Mrs.", first: "Jane", last: "Doe" },
],
childs: [
{ title: "Ms.", first: "Jane", last: "Doe" },
{ title: "Mr.", first: "Joe", last: "Doe" },
],
},
{
RoomType: {},
Price: {},
Messages: [],
CancellationPolicyStatus: "",
adults: [
{ title: "Mr.", first: "Johny", last: "Doe" },
{ title: "Mrs.", first: "Jane", last: "Doe" },
],
childs: [
{ title: "Ms.", first: "Jane", last: "Doe" },
{ title: "Mr.", first: "Jui", last: "Doe" },
],
},
];
const store = {};
const findDupe = (o, type) => {
const key = [o.first, o.last].join();
const tbl = (store[type] = store[type] || {});
if (!tbl[key]) {
tbl[key] = [o];
return;
}
if (tbl[key].length === 1) {
tbl[key][0].error = "Duplicate name, please update.";
}
o.error = "Duplicate name, please update.";
tbl[key].push(o);
};
data.forEach((record) => {
record.adults.forEach((adult) => findDupe(adult, "adults"));
record.childs.forEach((child) => findDupe(child, "childs"));
});
console.log(JSON.stringify(data, null, 4));
Edit: as requested - explanation of findDupe -
creates a "key" by combining first and lastname together
creates store[type] object if it doesn't exist
if the key made in 1 doesn't exist in the object made in 2, create the key as an array and store the current person in it - done
otherwise it's a duplicate - add it to the array in step 3
if it's the first duplicate, mark the first person in the array as a duplicate
mark this person as a duplicate
Create two objects (database) where first and last names will be stored, iterate your objects and check if first/last name exists in the database, if not, add them to the database:
const arr = [
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "John", "last": "Doe"},
{ "title": "Mrs.", "first": "Jane", "last": "Doe"}
],
"childs": [
{ "title": "Ms.", "first": "Jane", "last": "Doe"},
{ "title": "Mr.", "first": "Joe", "last": "Doe" }
]
},
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "Johny", "last": "Doe",},
{ "title": "Mrs.", "first": "Jane", "last": "Doe",}
],
"childs": [
{ "title": "Ms.", "first": "Jane", "last": "Doe"},
{ "title": "Mr.", "first": "Jui", "last": "Doe"}
]
},
];
function check(arr)
{
//we'll store names for both adults and children in these objects
const first = {},
last = {};
return arr.map(room =>
{
const checkDup = person =>
{
//check if this first/last name already exists in our database
if (first[person.first] !== undefined && last[person.last] !== undefined)
{
//set error property in current person object
person.error = "Duplicate name, please update.";
//set error property in the original person object
first[person.first].error = person.error;
}
else
{
//store names in the database
first[person.first] = person;
last[person.last] = person;
}
return person;
}
room.adults.forEach(checkDup);
room.childs.forEach(checkDup);
return room;
});
}
console.log(check(arr));
/*
[
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "John", "last": "Doe"},
{ "title": "Mrs.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." }
],
"childs": [
{ "title": "Ms.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." },
{ "title": "Mr.", "first": "Joe", "last": "Doe" }
]
},
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "Johny", "last": "Doe", },
{ "title": "Mrs.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." }
],
"childs": [
{ "title": "Ms.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." },
{ "title": "Mr.", "first": "Jui", "last": "Doe" }
]
},
]
*/
not to be a grammar nazzy, but it's children, not childs
There are probably better ways to do this, but this should suit your needs.
You'll need to loop over both of the arrays checking the names of each object.
Set the error for both adult and child if you come across a match.
Should also be worth noting that your parent array of these objects was not named (unless it is named props, I don't use Vue so I don't know if that is a convention or not) so you would have to loop through every object in the parent array to do this.
const namesArray = [];
// Loop over the adults array. Store the names and index to check against later
adults.forEach((adult, index) => {
let fullName = adult.first + adult.last;
namesArray.push({name: fullName, index: index});
}
// Loop over the child array
// If the name of a child is found in the namesArray, set the error for the child and the corresponding adult
children.forEach(child => {
let fullName = child.first + child.last;
namesArray.forEach(nameObject => {
if(nameObject.name === fullName) {
child.error = 'Duplicate name, please update.';
adults[nameObject.index].error = 'Duplicate name, please update.';
}
}
}

Javascript Array of Object: filter by multple AND conditions

My mocked data:
[
{
"id": 1,
"first_name": "Suzy",
"last_name": "Pinnell",
"email": "spinnell0#utexas.edu",
"gender": "Agender",
"image": "http://dummyimage.com/410x239.png/5fa2dd/ffffff",
"department": "Marketing",
"job_title": "Quality Control Specialist",
"skill": "Residential Homes"
},
{
"id": 2,
"first_name": "Enriqueta",
"last_name": "Folbig",
"email": "efolbig1#google.com.br",
"gender": "Male",
"image": "http://dummyimage.com/247x244.png/5fa2dd/ffffff",
"department": "Sales",
"job_title": "Environmental Specialist",
"skill": "MMC"
},
{
"id": 3,
"first_name": "Simmonds",
"last_name": "Acomb",
"email": "sacomb2#amazon.co.uk",
"gender": "Polygender",
"image": "http://dummyimage.com/315x256.png/dddddd/000000",
"department": "Human Resources",
"job_title": "Accountant",
"skill": "Xilinx"
},
{
"id": 4,
"first_name": "Bernita",
"last_name": "Hartman",
"email": "bhartman3#whitehouse.gov",
"gender": "Female",
"image": "http://dummyimage.com/305x275.png/dddddd/000000",
"department": "Support",
"job_title": "Account ExecutiveII",
"skill": "Airframe"
}
]
I found a similar question here:
javascript filter array multiple conditions
To define what to filter they pass an object:
var filter = {
gender: 'male',
department: 'Sales'
};
This works. It shows every object containing both keys.
+I tried to modify it, so I could use an array:*
var filter = {
gender: ['Male'],
department: ['Sales', 'Marketing']
};
My goal is to filter the data by the given values in the array. Only items should appear, which contain all males in sales and marketing.
I tried includes (inside filter and a for in loop), but it shows only the results of the first array, the second one is ignored. I am not sure how to achieve a AND condition inside the arrays for all of them.
Thank you.
You could store all entries in advance to prevent to get for each object of data to get the same entries array of the filters.
Filter entries to remove possible empty arrays.
Then take the entries and check if the value is the one of the data or if the filter contains an array, then check if the filter array contains the value from data.
const
data = [{ id: 1, first_name: "Suzy", last_name: "Pinnell", email: "spinnell0#utexas.edu", gender: "Agender", image: "http://dummyimage.com/410x239.png/5fa2dd/ffffff", department: "Marketing", job_title: "Quality Control Specialist", skill: "Residential Homes" }, { id: 2, first_name: "Enriqueta", last_name: "Folbig", email: "efolbig1#google.com.br", gender: "Male", image: "http://dummyimage.com/247x244.png/5fa2dd/ffffff", department: "Sales", job_title: "Environmental Specialist", skill: "MMC" }, { id: 3, first_name: "Simmonds", last_name: "Acomb", email: "sacomb2#amazon.co.uk", gender: "Polygender", image: "http://dummyimage.com/315x256.png/dddddd/000000", department: "Human Resources", job_title: "Accountant", skill: "Xilinx" }, { id: 4, first_name: "Bernita", last_name: "Hartman", email: "bhartman3#whitehouse.gov", gender: "Female", image: "http://dummyimage.com/305x275.png/dddddd/000000", department: "Support", job_title: "Account ExecutiveII", skill: "Airframe" }],
filter = { last_name: [], gender: ['Male'], department: ['Sales', 'Marketing'] },
filterEntries = Object
.entries(filter)
.filter(([, v]) => !Array.isArray(v) || v.length),
result = data.filter(o => filterEntries.every(([k, v]) =>
o[k] === v ||
Array.isArray(v) && v.includes(o[k])
));
console.log(result);
That's a good every use case :)
const data = [
{
"id": 1,
"first_name": "Suzy",
"last_name": "Pinnell",
"email": "spinnell0#utexas.edu",
"gender": "Agender",
"image": "http://dummyimage.com/410x239.png/5fa2dd/ffffff",
"department": "Marketing",
"job_title": "Quality Control Specialist",
"skill": "Residential Homes"
},
{
"id": 2,
"first_name": "Enriqueta",
"last_name": "Folbig",
"email": "efolbig1#google.com.br",
"gender": "Male",
"image": "http://dummyimage.com/247x244.png/5fa2dd/ffffff",
"department": "Sales",
"job_title": "Environmental Specialist",
"skill": "MMC"
},
{
"id": 3,
"first_name": "Simmonds",
"last_name": "Acomb",
"email": "sacomb2#amazon.co.uk",
"gender": "Polygender",
"image": "http://dummyimage.com/315x256.png/dddddd/000000",
"department": "Human Resources",
"job_title": "Accountant",
"skill": "Xilinx"
},
{
"id": 4,
"first_name": "Bernita",
"last_name": "Hartman",
"email": "bhartman3#whitehouse.gov",
"gender": "Female",
"image": "http://dummyimage.com/305x275.png/dddddd/000000",
"department": "Support",
"job_title": "Account ExecutiveII",
"skill": "Airframe"
}
]
const filter = {
gender: ['Male'],
department: ['Sales', 'Marketing']
}
const result = data.filter(item => (
Object.entries(filter).every(([key, arr]) => arr.includes(item[key]))
))
console.log(result)
Instead of negating the === operator, you can negate an includes call:
data = data.filter(function(item) {
for (var key in filter) {
if (item[key] === undefined || !filter[key].includes(item[key]))
return false;
}
return true;
});
You can acheive your expected result by iterating over your filter object and on the every iteration, checking target object can pass your filter or not (in below snippet I've used Object.entries and every method to do that), like this:
const data = [
{
"id": 1,
"first_name": "Suzy",
"last_name": "Pinnell",
"email": "spinnell0#utexas.edu",
"gender": "Agender",
"image": "http://dummyimage.com/410x239.png/5fa2dd/ffffff",
"department": "Marketing",
"job_title": "Quality Control Specialist",
"skill": "Residential Homes"
},
{
"id": 2,
"first_name": "Enriqueta",
"last_name": "Folbig",
"email": "efolbig1#google.com.br",
"gender": "Male",
"image": "http://dummyimage.com/247x244.png/5fa2dd/ffffff",
"department": "Sales",
"job_title": "Environmental Specialist",
"skill": "MMC"
},
{
"id": 3,
"first_name": "Simmonds",
"last_name": "Acomb",
"email": "sacomb2#amazon.co.uk",
"gender": "Polygender",
"image": "http://dummyimage.com/315x256.png/dddddd/000000",
"department": "Human Resources",
"job_title": "Accountant",
"skill": "Xilinx"
},
{
"id": 4,
"first_name": "Bernita",
"last_name": "Hartman",
"email": "bhartman3#whitehouse.gov",
"gender": "Female",
"image": "http://dummyimage.com/305x275.png/dddddd/000000",
"department": "Support",
"job_title": "Account ExecutiveII",
"skill": "Airframe"
}
];
const filter = {
gender: ['Male'],
department: ['Sales', 'Marketing']
}
const createFilterFun = filters => obj => Object.entries(filters).every( ([k, v]) => v.includes(obj[k]) );
const filterByGenderAndDepratment = createFilterFun(filter);
const result = data.filter(filterByGenderAndDepratment);
console.log(result)
try this
var itemsFilter = {
gender: ['Male'],
department: ['Sales', 'Marketing']
};
users= users.filter (function(item) {
var find=false;
for (var key in itemsFilter) {
find=false;
if (item[key] === undefined) return false;
for (var k in itemsFilter[key])
if (itemsFilter[key][k] == item[key]) find=true;
if (find==false) return false;
};
return find;
});

Object not replacing using spread operator

I want to replace existing object with new updated fields using spread operator. But I am not getting the correct result.
Below are my two objects.
let obj1 = [
{
"id": 1,
"name": "Michel",
"age": 34,
"email": "michel#gmail.com"
},
{
"id": 2,
"name": "Abby",
"age": 40,
"email": "abby#gmail.com"
},
{
"id": 3,
"name": "Gary",
"age": 40,
"email": "abby#gmail.com"
}
]
let newObj = {
"id": 3,
"name": "Gary",
"age": 23,
"email": "gary#gmail.com"
}
I can do it with .map. Below is my code.
let result = obj1.map(item => {
if (item.id === newObj.id) {
return {...item, ...newObj};
}
return item;
});
But I do not want to run the loop and want to acheive by spread operator only.
Example for spread. Which is not working. It's not replacing the object. Instead creating one more.
[...obj1, newObj];
Can someone help me?
JSBIN CODE SNIPPET
Spread syntax doesn't replace the object within array like you used it. Using map is the simplest and understandable way. However if you want to use spread syntax you would first need to find the index to be replaced and then use slice on array
let obj1 = [
{
"id": 1,
"name": "Michel",
"age": 34,
"email": "michel#gmail.com"
},
{
"id": 2,
"name": "Abby",
"age": 40,
"email": "abby#gmail.com"
},
{
"id": 3,
"name": "Gary",
"age": 40,
"email": "abby#gmail.com"
}
]
let newObj = {
"id": 3,
"name": "Gary",
"age": 23,
"email": "gary#gmail.com"
}
const idx = obj1.findIndex(item => item.id === newObj.id);
obj1 = [...obj1.slice(0, idx), newObj, ...obj1.slice(idx + 1)];
console.log(obj1);
Use Object.assign
The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.
let obj1 = [
{
"id": 1,
"name": "Michel",
"age": 34,
"email": "michel#gmail.com"
},
{
"id": 2,
"name": "Abby",
"age": 40,
"email": "abby#gmail.com"
},
{
"id": 3,
"name": "Gary",
"age": 40,
"email": "abby#gmail.com"
}
]
let newObj = {
"id": 3,
"name": "Gary",
"age": 23,
"email": "gary#gmail.com"
}
Object.assign(obj1[2], newObj);
console.log(obj1)
Using .find() to get the target obj
let obj1 = [
{
"id": 1,
"name": "Michel",
"age": 34,
"email": "michel#gmail.com"
},
{
"id": 2,
"name": "Abby",
"age": 40,
"email": "abby#gmail.com"
},
{
"id": 3,
"name": "Gary",
"age": 40,
"email": "abby#gmail.com"
}
]
let newObj = {
"id": 3,
"name": "Gary",
"age": 23,
"email": "gary#gmail.com"
}
const targetObj = obj1.find(obj => obj.id === newObj.id)
Object.assign(targetObj, newObj);
console.log(obj1)
you should normalize your data by id this way:
obj1 = {
1: {
"id": 1,
"name": "Michel",
"age": 34,
"email": "michel#gmail.com"
},
2: {
"id": 2,
"name": "Abby",
"age": 40,
"email": "abby#gmail.com"
},
3: {
"id": 3,
"name": "Gary",
"age": 40,
"email": "abby#gmail.com"
}
}
newObj = {
3: {
"id": 3,
"name": "Gary",
"age": 23,
"email": "gary#gmail.com"
}
}
this way you can use spread operator:
{ ...obj1, ...newObj }
in order to normalize you can use the reduce func this way:
const normalized = obj1.reduce((result, obj) => ({ ...result, [obj.id]: obj }), {})
Spread operator is magic but it won't do whatever you want, you will have to loop over and replace the object. Instead of doing a map(), I would prefer find(). The use Object.assign() to achieve what you want.
let obj1 = [
{
"id": 1,
"name": "Michel",
"age": 34,
"email": "michel#gmail.com"
},
{
"id": 2,
"name": "Abby",
"age": 40,
"email": "abby#gmail.com"
},
{
"id": 3,
"name": "Gary",
"age": 40,
"email": "abby#gmail.com"
}
]
let newObj = {
"id": 3,
"name": "Gary",
"age": 23,
"email": "gary#gmail.com"
}
let foundOb = obj1.find(e => e.id === newObj.id);
Object.assign(foundOb, newObj)
console.log(obj1)
You cannot use spread syntax in that way. One solution would be to find index of the object you want to replace by id property and then you could use spread syntax with slice method to create new array with replaced object.
let obj1 = [{"id":1,"name":"Michel","age":34,"email":"michel#gmail.com"},{"id":2,"name":"Abby","age":40,"email":"abby#gmail.com"},{"id":3,"name":"Gary","age":40,"email":"abby#gmail.com"}]
let newObj = {"id":3,"name":"Gary","age":23,"email":"gary#gmail.com"}
const index = obj1.findIndex(({id}) => id == newObj.id)
const result = [...obj1.slice(0, index), newObj, ...obj1.slice(index + 1)]
console.log(result)
I would do something like:
updatedObj = [obj1.map((entry) => entry.id !== newObj.id), newObj]
This would give me the updated object with minimal syntax

How to return multiple values with the method array.from and new set

I would like to know if it is possible from an array of objects to retrieve several unique values with the method array.from new set.
For example :
this.data = [
{
"_id": "5bf57b965401169dd81c2a51",
"age": 35,
"name": "Paige Zamora",
"gender": "female",
"company": "AUTOMON",
"reference_id": "12"
},
{
"_id": "5bf57b96c2c3b88adff4b972",
"age": 40,
"name": "Jennifer Carr",
"gender": "female",
"company": "SYNKGEN",
"reference_id": "11"
},
{
"_id": "5bf57b969dd839926db78767",
"age": 38,
"name": "Weaver Rosales",
"gender": "male",
"company": "ETERNIS",
"reference_id": "10"
},
{
"_id": "5bf57b968c845ea691e76c84",
"age": 31,
"name": "Myers Pickett",
"gender": "male",
"company": "ETERNIS",
"reference_id": "10"
},
{
"_id": "5bf57b96998c44eff083d3fa",
"age": 36,
"name": "Dona Nicholson",
"gender": "female",
"company": "ETERNIS",
"reference_id": "10"
}
]
I would like to retrieve the following unique values: reference_id and the company associated with the reference_id, which would give this:
[{12, AUTOMON}, {11, SYNKGEN}, {10, ETERNIS}]
I thought I would use this method:
const list = Array.from (new Set (this.data.map ({reference_id}) => reference_id)));
what returns :
[12,11,10]
I do not know if this method can be used to return multiple values like the list above ?
You could use a JSON with the wanted data and take then the parsed values as result.
Why a string instead of an object, you may ask. The problem here is every new object with the wanted properties is a new object, and not the same.
Set works wite a single primitive or object and checks, if an object's reference is the same. By taking a string, the value could be checked and you get unique strings in the set. This required to convert the JSON back to an object.
var data = [{ _id: "5bf57b965401169dd81c2a51", age: 35, name: "Paige Zamora", gender: "female", company: "AUTOMON", reference_id: "12" }, { _id: "5bf57b96c2c3b88adff4b972", age: 40, name: "Jennifer Carr", gender: "female", company: "SYNKGEN", reference_id: "11" }, { _id: "5bf57b969dd839926db78767", age: 38, name: "Weaver Rosales", gender: "male", company: "ETERNIS", reference_id: "10" }, { _id: "5bf57b968c845ea691e76c84", age: 31, name: "Myers Pickett", gender: "male", company: "ETERNIS", reference_id: "10" }, { _id: "5bf57b96998c44eff083d3fa", age: 36, name: "Dona Nicholson", gender: "female", company: "ETERNIS", reference_id: "10" }],
unique = Array.from(
new Set(
data.map(({ reference_id, company }) =>
JSON.stringify({ reference_id, company }))
),
json => JSON.parse(json)
);
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can also group them in a Map (ignoring any repetitions and where keys are the string representations of reference_id and company) and return an array from its values:
var data = [{
"_id": "5bf57b965401169dd81c2a51",
"age": 35,
"name": "Paige Zamora",
"gender": "female",
"company": "AUTOMON",
"reference_id": "12"
},
{
"_id": "5bf57b96c2c3b88adff4b972",
"age": 40,
"name": "Jennifer Carr",
"gender": "female",
"company": "SYNKGEN",
"reference_id": "11"
},
{
"_id": "5bf57b969dd839926db78767",
"age": 38,
"name": "Weaver Rosales",
"gender": "male",
"company": "ETERNIS",
"reference_id": "10"
},
{
"_id": "5bf57b968c845ea691e76c84",
"age": 31,
"name": "Myers Pickett",
"gender": "male",
"company": "ETERNIS",
"reference_id": "10"
},
{
"_id": "5bf57b96998c44eff083d3fa",
"age": 36,
"name": "Dona Nicholson",
"gender": "female",
"company": "ETERNIS",
"reference_id": "10"
}
];
var res = Array.from(data.reduce((acc, {reference_id, company}) => {
acc.set(`${reference_id},${company}`, {reference_id, company});
return acc;
}, new Map()).values());
console.log(res);
Try this:
this.data.map((el) =>{ return {age: el.age, company: el.company} })
// You get this array
//0: {age: 35, company: "AUTOMON"}
//1: {age: 40, company: "SYNKGEN"}
//2: {age: 38, company: "ETERNIS"}
//3: {age: 31, company: "ETERNIS"}
//4: {age: 36, company: "ETERNIS"}
{12, AUTOMON} doesn't make sense, obj is { key: value, key: value...}

How to sort a multidimensional object in JavaScript [duplicate]

This question already has answers here:
Sorting Object by sub-object property
(4 answers)
Closed 7 years ago.
How to sort the objects by age value?
I have the following object structure
{
"men": {
"20114": {
"id": "20114",
"name": "Peter",
"age": "21"
},
"28957": {
"id": "28957",
"name": "Paul",
"age": "20"
}
},
"women": {
"8957": {
"id": "8957",
"name": "Rose",
"age": "24"
},
"2178": {
"id": "2178",
"name": "Sara",
"age": "22"
}
},
}
I know, that I can sort arrays like this
groups.sort(function(a, b) {
return b.age - a.age;
});
but how to do this with objects?
It would be a lot easier to sort your data if you could change your structure to the JSON model below:
var data = [
{
"id": "20114",
"name": "Peter",
"age": "21",
"gender": "men"
},
{
"id": "28957",
"name": "Paul",
"age": "20",
"gender": "men"
},
{
"id": "8957",
"name": "Rose",
"age": "24",
"gender": "women"
},
{
"id": "2178",
"name": "Sara",
"age": "22",
"gender": "women"
}
]
data.sort(function(a, b) {
return parseFloat(a.age) - parseFloat(b.age);
});
data.sort()
document.write(JSON.stringify(data))
function sortfunc(prop){
return function(obj1,obj2){
var val1 = obj1[prop];
var val2 = obj2[prop];
return val1 - val2;
};
}
groups.sort(sortfunc(prop));
pass prop as property name

Categories

Resources