I have the following json object in javascript:
employeeRecords = [
{
"empID" : "7002",
"company" : "Google",
"group" : "Chrome",
"id" : "D-2005",
"city" : "New York",
"date" : "2018-05-01"
},
{
"empID" : "9002",
"company" : "Apple",
"group" : "iPhone",
"id" : "D-2014",
"city" : "Singapore"
"date": "2019-07-15"
},
{
"empID" : "7002",
"company" : "Google",
"group" : "Android",
"id" : "H-2007",
"city" : "London"
"date": "2018-05-01"
},
{
"empID" : "7002"
"company" : "Google",
"group" : "Android",
"id" : "K-2007",
"city" : "London"
"date": "2019-06-18"
},
{
"empID" : "9002",
"company" : "Apple",
"group" : "Laptop",
"id" : "N-2012",
"city" : "Japan"
"date": "2019-07-15"
}
]
The requirement is to group this json object, if the empID, company and the date is equal. If those key values are equal then the group field should be concatenated. I need to get this using JavaScript.
So the result should be like the following:
employeeRecords = [
{
"empID" : "7002",
"company" : "Google",
"group" : "Chrome-Android",
"id" : "D-2005",
"city" : "New York",
"date" : "2018-05-01"
},
{
"empID" : "9002",
"company" : "Apple",
"group" : "iPhone-Laptop",
"id" : "D-2014",
"city" : "Singapore"
"date": "2019-07-15"
},
{
"empID" : "7002"
"company" : "Google",
"group" : "Android",
"id" : "K-2007",
"city" : "London"
"date": "2019-06-18"
}
]
Any help to achieve this in JavaScript please? Thanks in advance.
CodePudding user response:
The first solution that comes to my mind is to add an element to a new list according to a control while traversing all the elements with the Array.prototype.forEach method.
const fixedRecords = [];
employeeRecords.forEach(record => {
let index = fixedRecords.findIndex(fr => fr.empID === record.empID && fr.date === record.date && fr.company === record.company)
if(index !== -1) {
fixedRecords[index] = {
...fixedRecords[index],
group: fixedRecords[index].group '-' record.group
}
}else {
fixedRecords.push(record);
}
})
This method will work. However, consider this; The findIndex function running for each list element means that this list will run for the number of elements for each element count (n * n). Therefore, if your list is large, it will not be very performant.
CodePudding user response:
This uses reduce()
and a JS object to compute the groups and will run in O(n)
which is (at least for large arrays) considerably quicker than an implementation with includes()
, find()
or other nested loop approaches which take O(n²)
.
Just a note: I am not sure why you would want
id
andcity
in the output as this is meaningless information as this is the information for the first employee of a group and may or may not be true for all employees in that group, hence it's useless information that could potentially be confusing as it looks like a legitimate employee.
const employeeRecords = [ { empID: "7002", company: "Google", group: "Chrome", id: "D-2005", city: "New York", date: "2018-05-01", }, { empID: "9002", company: "Apple", group: "iPhone", id: "D-2014", city: "Singapore", date: "2019-07-15", }, { empID: "7002", company: "Google", group: "Android", id: "H-2007", city: "London", date: "2018-05-01", }, { empID: "7002", company: "Google", group: "Android", id: "K-2007", city: "London", date: "2019-06-18", }, { empID: "9002", company: "Apple", group: "Laptop", id: "N-2012", city: "Japan", date: "2019-07-15", }, ]; const resultObj = employeeRecords.reduce((acc, emp) => { // concatenate the key (all criteria together build the key) const key = `${emp.empID}-${emp.company}-${emp.date}`; // if we already have a value with that key, add the group of the current employee if(acc.hasOwnProperty(key)) acc[key].group = `-${emp.group}`; // if we don't have a value with that key add that employee else acc[key] = emp; return acc; }, {}); const result = Object.values(resultObj); console.log(result);