Reputation: 35
Here is my current Array looks like:
{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' },
{ entity: 'B', type: 'request', requestUrl: 'val1' },
{ entity: 'B', type: 'response', responseUrl: 'val1' },
{ entity: 'C', type: 'request', requestUrl: 'val1' },
{ entity: 'C', type: 'response', responseUrl: 'val1' },
{ entity: 'D', type: 'request', requestUrl: 'val1' },
{ entity: 'D', type: 'response', responseUrl: 'val1' },
{ entity: 'DADA', type: '', responseUrl: 'val1' }
Each row contains an attribute named 'entity' which has 2 rows : one corresponding to request and other corresponding to response. I need to merge the request and response rows, and have the data as one row only. (The attribute 'type' doesn't matter in the merged row, but need to have all other attributes). So the solution would be something like:
[{"entity":"A","type":"response","requestUrl":"val1","responseUrl":"val1"},
{"entity":"B","type":"response","requestUrl":"val1","responseUrl":"val1"},
{"entity":"C","type":"response","requestUrl":"val1","responseUrl":"val1"},
{"entity":"D","type":"response","requestUrl":"val1","responseUrl":"val1"}]
Currently, this is what I have: https://www.w3schools.com/code/tryit.asp?filename=FUHGQN2JON75
Not sure if that's the best way to do it. Recommendations welcome on how to improve this solution.
Thanks.
Upvotes: 3
Views: 2410
Reputation: 50291
Use reduce to create a new array. But at the same time the out put should be checked if the order of the objects are changed in the array.
Let us consider these two objects
{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' }
Consider the first object , and in this object we will check which key is present in second object but now in the first object then add that key in the first object.
let orgArray = [{
entity: 'A',
type: 'response',
responseUrl: 'val1'
},
{
entity: 'A',
type: 'request',
requestUrl: 'val1'
},
{
entity: 'B',
type: 'request',
requestUrl: 'val1'
},
{
entity: 'B',
type: 'response',
responseUrl: 'val1'
},
{
entity: 'C',
type: 'request',
requestUrl: 'val1'
},
{
entity: 'C',
type: 'response',
responseUrl: 'val1'
},
{
entity: 'D',
type: 'request',
requestUrl: 'val1'
},
{
entity: 'D',
type: 'response',
responseUrl: 'val1'
},
{
entity: 'DADA',
type: '',
responseUrl: 'val1'
}
]
let newArray = orgArray.reduce(function(acc, curr) {
//get the index of the object where entity matches
let getIndexOfEntity = acc.findIndex(function(item) {
return item.entity === curr.entity
})
//if there is no such entity then it will give -1
if (getIndexOfEntity === -1) {
// in that case push the object
acc.push(curr)
} else {
// if entity exist
//now check which key is missing from the
// getting all the keys from both the object
let getAllKeyFromAccObj = Object.keys(acc[getIndexOfEntity]);
let getAllKeyFromCurrObj = Object.keys(curr)
// looping through the key and adding the missing key
getAllKeyFromCurrObj.forEach(function(item) {
if (getAllKeyFromAccObj.indexOf(item) === -1) {
acc[getIndexOfEntity][item] = curr[item]
}
})
}
return acc;
}, [])
console.log(newArray)
Upvotes: 0
Reputation: 4636
Assuming request and response are consecutive we can just use spread operators for merging
const data = [{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' },
{ entity: 'B', type: 'request', requestUrl: 'val1' },
{ entity: 'B', type: 'response', responseUrl: 'val1' },
{ entity: 'C', type: 'request', requestUrl: 'val1' },
{ entity: 'C', type: 'response', responseUrl: 'val1' },
{ entity: 'D', type: 'request', requestUrl: 'val1' },
{ entity: 'D', type: 'response', responseUrl: 'val1' },
{ entity: 'DADA', type: '', responseUrl: 'val1' }]
const newData = data.reduce((acc, item, index) => {
if (index % 2 || !item.type) return acc;
acc.push({...item, ...data[index+1]})
return acc;
}, [])
console.log(newData)
Upvotes: 0
Reputation: 39322
You can use Map
and forEach()
:
let data = [{ entity: 'A', type: 'request', requestUrl: 'val1' },{ entity: 'A', type: 'response', responseUrl: 'val1' },{ entity: 'B', type: 'request', requestUrl: 'val1' },{ entity: 'B', type: 'response', responseUrl: 'val1' },{ entity: 'C', type: 'request', requestUrl: 'val1' },{ entity: 'C', type: 'response', responseUrl: 'val1' },{ entity: 'D', type: 'request', requestUrl: 'val1' },{ entity: 'D', type: 'response', responseUrl: 'val1' }];
let result = ((a, m) => {
a.forEach(o => {
m.set(o.entity, Object.assign((m.get(o.entity) || {}), o));
});
return [...m.values()];
})(data, new Map());
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 947
You can use a Map for this that keeps track of all your entity objects.
Later you can convert the Map
back to an array.
const input = [
{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' },
{ entity: 'B', type: 'request', requestUrl: 'val1' },
{ entity: 'B', type: 'response', responseUrl: 'val1' },
{ entity: 'C', type: 'request', requestUrl: 'val1' },
{ entity: 'C', type: 'response', responseUrl: 'val1' },
{ entity: 'D', type: 'request', requestUrl: 'val1' },
{ entity: 'D', type: 'response', responseUrl: 'val1' },
{ entity: 'DADA', type: '', responseUrl: 'val1' }
]
const entityMap = new Map();
input.forEach(element => {
let currentEntity = entityMap.get(element.entity) || {};
entityMap.set(element.entity, {
...currentEntity,
...element,
})
});
return Array.from(entityMap.values());
Upvotes: 0
Reputation: 5698
You can use this answer
var arr = [{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' },
{ entity: 'B', type: 'request', requestUrl: 'val1' },
{ entity: 'B', type: 'response', responseUrl: 'val1' },
{ entity: 'C', type: 'request', requestUrl: 'val1' },
{ entity: 'C', type: 'response', responseUrl: 'val1' },
{ entity: 'D', type: 'request', requestUrl: 'val1' },
{ entity: 'D', type: 'response', responseUrl: 'val1' },
{ entity: 'DADA', type: '', responseUrl: 'val1' }];
var res = Array.from(
new Set(arr.filter(x => x.type).map(x=>x.entity))
)
.map(el => arr.find(obj => obj.entity === el))
console.log(res);//
/*
[{"entity":"A","type":"request","requestUrl":"val1"},
{"entity":"B","type":"request","requestUrl":"val1"},
{"entity":"C","type":"request","requestUrl":"val1"},
{"entity":"D","type":"request","requestUrl":"val1"}]
*/
Upvotes: 0
Reputation: 26844
One option is to use reduce
to group your array into an object. Use the entity
as the key. Use Object.assign
to convert the objects. Use Object.values
to convert the object into an array.
var arr = [{"entity":"A","type":"request","requestUrl":"val1"},{"entity":"A","type":"response","responseUrl":"val1"},{"entity":"B","type":"request","requestUrl":"val1"},{"entity":"B","type":"response","responseUrl":"val1"},{"entity":"C","type":"request","requestUrl":"val1"},{"entity":"C","type":"response","responseUrl":"val1"},{"entity":"D","type":"request","requestUrl":"val1"},{"entity":"D","type":"response","responseUrl":"val1"},{"entity":"DADA","type":"","responseUrl":"val1"}];
var result = Object.values(arr.reduce((c, v) => {
c[v.entity] = Object.assign(c[v.entity] || {}, v);
return c;
}, {}));
console.log(result);
Upvotes: 2
Reputation: 30739
You can use Array.reduce()
for that:
var arr = [{ entity: 'A', type: 'request', requestUrl: 'val1' },
{ entity: 'A', type: 'response', responseUrl: 'val1' },
{ entity: 'B', type: 'request', requestUrl: 'val1' },
{ entity: 'B', type: 'response', responseUrl: 'val1' },
{ entity: 'C', type: 'request', requestUrl: 'val1' },
{ entity: 'C', type: 'response', responseUrl: 'val1' },
{ entity: 'D', type: 'request', requestUrl: 'val1' },
{ entity: 'D', type: 'response', responseUrl: 'val1' },
{ entity: 'DADA', type: '', responseUrl: 'val1' }];
var res = arr.reduce((acc, item)=>{
var existObj = acc.find(obj => obj.entity === item.entity);
if(!existObj){
acc.push(item);
} else {
existObj['responseUrl'] = item.responseUrl;
}
return acc;
}, []);
console.log(res);
Upvotes: 0