Reputation: 17
I have an array of objects
var data = [
{
"date": "2016-07-18T00:00:00.000+0000",
"boundaryStats": [
{
"crop": 'Wheat',
"yield": 27,
},
{
"crop": 'Maize',
"yield": 48,
}
]
},
{
"date": "2020-03-18T00:00:00.000+0000",
"boundaryStats": [
{
"crop": "garlic",
"yield": 12,
},
{
"crop": "Wheat",
"yield": 12,
}
]
},
{
"date": "2020-07-18T00:00:00.000+0000",
"boundaryStats": [{
"crop": "Onion",
"yield": 1,
}
]
}
];
How can I get the output as below only unique crop name will be added and the length of data is based on length of the input array date, 0
if there is no data for the particular date
[{
"label": "Wheat",
"data": [27,12,0]
},
{
"label": "Maize",
"data": [48,0,0]
},
{
"label": "garlic",
"data": [0,12,0]
},
{
"label": "Onion",
"data": [0,0,1]
}
]
I tried
main = [];
resultObj = new Array(this.data.length).fill(0);
this.data.forEach(e=>{
e.boundaryStats.forEach((ei,i)=>{
const checkUsername = obj => obj.label === ei.crop;
if(!main.some(checkUsername)){
main.push({
'label':ei.crop,
'data':resultObj
})
}
})
})
but yield I am not able to add a particular data index
Upvotes: 1
Views: 100
Reputation: 5308
You can first maintain a date Object with its initial count, then you can reduce it:
var data = [ { "date": "2016-07-18T00:00:00.000+0000", "boundaryStats": [ { "crop": 'Wheat', "yield": 27, }, { "crop": 'Maize', "yield": 48, } ] }, { "date": "2020-03-18T00:00:00.000+0000", "boundaryStats": [ { "crop": "garlic", "yield": 12, }, { "crop": "Wheat", "yield": 12, } ] }, { "date": "2020-07-18T00:00:00.000+0000", "boundaryStats": [{ "crop": "Onion", "yield": 1, } ] }];
var datesOrder = Object.fromEntries(data.map(({date})=>([new Date(date).toLocaleDateString(),0])));
result = Object.values(data.reduce((acc, {date, boundaryStats})=>{
boundaryStats.forEach(k=>{
acc[k.crop] = acc[k.crop] || {label:k.crop, data:{...datesOrder}};
acc[k.crop].data[new Date(date).toLocaleDateString()] = k.yield;
});
return acc;
},{}))
.map(({label, data})=>({label, data:Object.values(data)}));
console.log(result);
Upvotes: 0
Reputation: 4241
We can do it with reduce:
const dateArr = data.map(item => (new Date(item.date)).toLocaleString()); //can be sorted if needed
console.log(dateArr);
const tempOut = data.reduce((aggObj, item) => {
item.boundaryStats.forEach(stat => {
const statDate = (new Date(item.date)).toLocaleString();
if (!aggObj[stat.crop]){
aggObj[stat.crop] = {label: stat.crop, data: {}};
for (let date of dateArr){
aggObj[stat.crop].data[date] = 0;
}
}
aggObj[stat.crop].data[statDate] += stat.yield;
})
return aggObj;
}, {})
//console.log(tempOut)
const finalOut = Object.values(tempOut).map(crop => {
crop.data = Object.values(crop.data);
return crop
});
console.log(finalOut);
<script id="initData">
const data = [
{
"date": "2016-07-18T00:00:00.000+0000",
"boundaryStats": [
{
"crop": 'Wheat',
"yield": 27,
},
{
"crop": 'Maize',
"yield": 48,
}
]
},
{
"date": "2020-03-18T00:00:00.000+0000",
"boundaryStats": [
{
"crop": "garlic",
"yield": 12,
},
{
"crop": "Wheat",
"yield": 12,
}
]
},
{
"date": "2020-07-18T00:00:00.000+0000",
"boundaryStats": [{
"crop": "Onion",
"yield": 1,
}
]
}
];
</script>
Upvotes: 0
Reputation: 15268
Uses an object map to collect values. map to desired {label,data} objects at the end.
const map = {}
data.forEach(({boundaryStats: b},i)=>b.forEach(({crop, yield})=>{
map[crop] = map[crop] || Array(data.length).fill(0)
map[crop][i] = yield
}))
console.log(
Object.entries(map).map(([crop,yield])=>({label:crop, data:yield}))
)
<script>
var data = [
{
"date": "2016-07-18T00:00:00.000+0000",
"boundaryStats": [
{
"crop": 'Wheat',
"yield": 27,
},
{
"crop": 'Maize',
"yield": 48,
}
]
},
{
"date": "2020-03-18T00:00:00.000+0000",
"boundaryStats": [
{
"crop": "garlic",
"yield": 12,
},
{
"crop": "Wheat",
"yield": 12,
}
]
},
{
"date": "2020-07-18T00:00:00.000+0000",
"boundaryStats": [{
"crop": "Onion",
"yield": 1,
}
]
}
];
</script>
Upvotes: 1
Reputation: 386578
You could group with an object and get the values.
var data = [{ date: "2016-07-18T00:00:00.000+0000", boundaryStats: [{ crop: "Wheat", yield: 27 }, { crop: "Maize", yield: 48 }] }, { date: "2020-03-18T00:00:00.000+0000", boundaryStats: [{ crop: "garlic", yield: 12 }, { crop: "Wheat", yield: 12 }] }, { date: "2020-07-18T00:00:00.000+0000", boundaryStats: [{ crop: "Onion", yield: 1 }] }],
result = Object.values(data.reduce((r, { date, boundaryStats }, i, { length }) => {
boundaryStats.forEach(({ crop: label, yield: value }) => {
if (!r[label]) r[label] = { label, data: Array(length).fill(0) };
r[label].data[i] = value;
});
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation:
var data = [
{
"date": "2016-07-18T00:00:00.000+0000",
"boundaryStats": [
{
"crop": 'Wheat',
"yield": 27,
},
{
"crop": 'Maize',
"yield": 48,
}
]
},
{
"date": "2020-03-18T00:00:00.000+0000",
"boundaryStats": [
{
"crop": "garlic",
"yield": 12,
},
{
"crop": "Wheat",
"yield": 12,
}
]
},
{
"date": "2020-07-18T00:00:00.000+0000",
"boundaryStats": [{
"crop": "Onion",
"yield": 1,
}
]
}
];
main = [];
data.forEach(e=>{
e.boundaryStats.forEach((ei,i)=>{
const checkUsername = obj => obj.label === ei.crop;
if(!main.some(checkUsername)){
main.push({
'label':ei.crop,
'data': [ei.yield]
})
} else {
let obj = main.find(m => m.label === ei.crop);
obj.data.push(ei.yield);
}
})
})
console.log(main)
Upvotes: 0