Merge array of an object based on a common field - javascript

I have an object that looks like as follows:
[
{
"Net_Amount": 499,
"Date": "2022-01-09T18:30:00.000Z",
"Scheme_Name": "CUSTOMERWINBACKJCA01",
"Month": "Jan"
},
{
"Net_Amount": 902,
"Date": "2022-01-09T18:30:00.000Z",
"Scheme_Name": "CUSTOMERWINBACKJCA02",
"Month": "Jan"
},
{
"Net_Amount": 1860,
"Date": "2022-10-01T18:30:00.000Z",
"Scheme_Name": "CUSTOMERCONNECTJCA",
"Month": "Oct"
},
{
"Net_Amount": 1889,
"Date": "2022-11-01T18:30:00.000Z",
"Scheme_Name": "CUSTOMERCONNECTJCA",
"Month": "Nov"
}
]
Now, if you will look carefully, I have a common field Month in the objects and I want merge the objects based on this common field only. How I want my object to be formatted is as :
[
{
"Month": "Jan",
"varData": [{
"Net_Amount": 499,
"Date": "2022-01-09T18:30:00.000Z",
"Scheme_Name": "CUSTOMERWINBACKJCA01"
},
{
"Net_Amount": 902,
"Date": "2022-01-09T18:30:00.000Z",
"Scheme_Name": "CUSTOMERWINBACKJCA02"
}]
},
{
"Month": "Oct",
"varData": [{
"Net_Amount": 1860,
"Date": "2022-10-01T18:30:00.000Z",
"Scheme_Name": "CUSTOMERCONNECTJCA"
}]
},
{
"Month": "Nov",
"varData": [{
"Net_Amount": 1889,
"Date": "2022-11-01T18:30:00.000Z",
"Scheme_Name": "CUSTOMERCONNECTJCA"
}]
}
]
I can do it by iterating over the array and checking if month is same, then pushing the other key and its value of object in the varData but I want to know if there is any shortcut or inbuilt function which I can use to achieve my purpose.

I don't think that there is some better built-in solution then iterating the array.
But if you use month names as keys then the code could be quite straightforward (the output is not exactly the same but quite similarly structured).
const result = {}
for (const entry of list) {
if (!result[entry.Month]) {
result[entry.Month] = []
}
result[entry.Month].push(entry)
}
See jsfiddle.
If you need the output that is exactly specified in the question then you can use the following code:
let result = {}
for (const entry of list) {
const month = entry.Month
if (!result[month]) {
result[month] = {
"Month": month,
"varData": []
}
}
delete entry.Month
result[month].varData.push(entry)
}
result = Object.values(result)
See jsfiddle

const data = [{"Net_Amount":499,"Date":"2022-01-09T18:30:00.000Z","Scheme_Name":"CUSTOMERWINBACKJCA01","Month":"Jan"},{"Net_Amount":902,"Date":"2022-01-09T18:30:00.000Z","Scheme_Name":"CUSTOMERWINBACKJCA02","Month":"Jan"},{"Net_Amount":1860,"Date":"2022-10-01T18:30:00.000Z","Scheme_Name":"CUSTOMERCONNECTJCA","Month":"Oct"},{"Net_Amount":1889,"Date":"2022-11-01T18:30:00.000Z","Scheme_Name":"CUSTOMERCONNECTJCA","Month":"Nov"}]
console.log([...new Set(data.map(i=>i.Month))].map(Month=>
({Month, varData: data.filter(({Month:m})=>m===Month).map(({Month,...o})=>o)})))

const dataArr = [
{
Net_Amount: 499,
Date: "2022-01-09T18:30:00.000Z",
Scheme_Name: "CUSTOMERWINBACKJCA01",
Month: "Jan",
},
{
Net_Amount: 902,
Date: "2022-01-09T18:30:00.000Z",
Scheme_Name: "CUSTOMERWINBACKJCA02",
Month: "Jan",
},
{
Net_Amount: 1860,
Date: "2022-10-01T18:30:00.000Z",
Scheme_Name: "CUSTOMERCONNECTJCA",
Month: "Oct",
},
{
Net_Amount: 1889,
Date: "2022-11-01T18:30:00.000Z",
Scheme_Name: "CUSTOMERCONNECTJCA",
Month: "Nov",
},
];
const outputObj = dataArr.reduce((acc, crt) => {
acc[crt.Month] ??= [];
acc[crt.Month].push(crt);
return acc;
}, {});
const outputArr = Object.values(outputObj).map((item) => ({ Month: item[0].Month, varData: item }));
console.log(outputArr);

Related

JS group by month/year of date

I have an array with date and id's I want to convert it group by month and by year year
oldest date/month should be at first
let myArray = [
{project_id: 444, date: "2021-08-17 14:33:49"},
{project_id: 444, date: "2021-08-16 14:33:50"},
{project_id: 555, date: "2020-08-16 14:33:50"},
{project_id: 666, date: "2020-08-17 12:33:50"},
{project_id: 666, date: "2020-09-17 12:33:50"},
{project_id: 666, date: "2020-09-17 12:33:50"},
];
The below array is my actual requirement that is manually converted from the above array
eg:
[
{
"month_year": "Aug 2020",
"data": [
{
"date": "2020-08-16 14:33:50",
"project_id": 666
},
{
"date": "2020-08-17 12:33:50",
"project_id": 777
}
]
},
{
"month_year": "Sep 2020",
"data": [
{
"date": "22020-09-17 12:33:50",
"project_id": 666
},
{
"date": "2020-09-17 12:33:50",
"project_id": 666
}
]
},
{
"month_year": "Aug 2021",
"data": [
{
"date": "2021-08-17 14:33:49",
"project_id": 444
},
{
"date": "2021-08-16 14:33:50",
"project_id": 444
}
]
},
]
Something like this should work:
function groupByDate(list) {
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
];
let result = [];
for (let obj of list) {
let objDate = new Date(obj.date);
let monthYear = `${monthNames[objDate.getMonth()]} ${objDate.getFullYear()}`;
let foundMatch = false;
for (let i = 0; i < result.length; i++) {
if (result[i].month_year === monthYear) {
result[i].data.push(obj);
foundMatch = true;
break;
}
}
if (!foundMatch) {
result.push({
"month_year": monthYear,
"data": [obj]
});
}
}
return result;
}
Basically it loops over each object in the list, and if the current date (month and year only) hasn't already been processed, it will add another json object to the result list. If the current date have been processed before, it adds it to the correct json.
Working JSFiddle:
https://jsfiddle.net/dfhg41sx/1/

How to return and get the sum of object properties based on given filters?

I have the following object.
var data = [
{"Name":"ABC","Dept":"First","FY":"2016","Quarter":"1","Month":"April","Total":"100"},
{"Name":"ABC","Dept":"Second","FY":"2017","Quarter":"2","Month":"May","Total":"200"},
{"Name":"ABC","Dept":"First","FY":"2016","Quarter":"1","Month":"June","Total":"150"},
{"Name":"DEF","Dept":"First","FY":"2016","Quarter":"1","Month":"April","Total":"200"},
{"Name":"DEF","Dept":"Second","FY":"2017","Quarter":"2","Month":"May","Total":"100"},
{"Name":"DEF","Dept":"First","FY":"2016","Quarter":"1","Month":"June","Total":"500"}
]
I want to filter on the abve object to get:
a. I want to return Total based on my filters(ex: If I give Name as ABC, Dept as First, FY as 2016, Quarter as 1, Month as April, then it should filter/return the Total i.e 100 for the given filters)
b. Similarly, I want to return Sum of all the Totals(ex: if I give Name as ABC, Dept as First, FY as 2016 - then it should return sum of the required Total values(i.e 100+150=250) for the given FY 2016 only)
Please help me in this requirement, how can I achieve, Thanks.
I have tried below, but it is giving all the results for given Name(ex: If I give Name as ABC, then it is returning all the details ABC only)
return getData().then(res => {
res.data.filter(customerDetails =>{
if(customerDetails.Name === name && customerDetails.FY === fy && customerDetails.Quarter === quarter && customerDetails.Month === month && customerDetails.Dept === dept)
agent.add(`Details: ${name}, Dept: ${customerDetails.Dept},
FY: ${customerDetails.FY}, Quarter: ${customerDetails.Quarter}, Month: ${customerDetails.Month},
Total: ${customerDetails.Total} `);
});
});
You can use Array.filter() to do that. Filter data based on passed values, and then add Total values of filtered data to get final total.
var data = [{ "Name": "ABC", "Dept": "First", "FY": "2016", "Quarter": "1", "Month": "April", "Total": "100" }, { "Name": "ABC", "Dept": "Second", "FY": "2017", "Quarter": "2", "Month": "May", "Total": "200" }, { "Name": "ABC", "Dept": "First", "FY": "2016", "Quarter": "1", "Month": "June", "Total": "150" }, { "Name": "DEF", "Dept": "First", "FY": "2016", "Quarter": "1", "Month": "April", "Total": "200" }, { "Name": "DEF", "Dept": "Second", "FY": "2017", "Quarter": "2", "Month": "May", "Total": "100" }, { "Name": "DEF", "Dept": "First", "FY": "2016", "Quarter": "1", "Month": "June", "Total": "500" }];
function getTotal(filters) {
var total = 0;
const filteredData = data.filter(item => {
for (var key in filters) {
if (item[key] != filters[key]) {
return false;
}
}
return true;
});
filteredData.forEach(value => total += Number(value.Total));
return total;
}
console.log(getTotal({ "Name": "ABC", "Dept": "First", "FY": "2016" }));
console.log(getTotal({"Name": "DEF" }));
You could take an object with the wanted filter values and filter the array and return the sum of all Total.
function getTotal(data, filters) {
var f = Object.entries(filters);
return data
.filter(o => f.every(([k, v]) => o[k] == v))
.reduce((s, { Total }) => s + +Total, 0);
}
var data = [{ Name: "ABC", Dept: "First", FY: "2016", Quarter: "1", Month: "April", Total: "100" }, { Name: "ABC", Dept: "Second", FY: "2017", Quarter: "2", Month: "May", Total: "200" }, { Name: "ABC", Dept: "First", FY: "2016", Quarter: "1", Month: "June", Total: "150" }, { Name: "DEF", Dept: "First", FY: "2016", Quarter: "1", Month: "April", Total: "200" }, { Name: "DEF", Dept: "Second", FY: "2017", Quarter: "2", Month: "May", Total: "100" }, { Name: "DEF", Dept: "First", FY: "2016", Quarter: "1", Month: "June", Total: "500" }];
console.log(getTotal(data, { Name: 'ABC', Dept: 'First', FY: 2016, Quarter: 1, Month: 'April' })); // 100
console.log(getTotal(data, { Name: 'ABC', Dept: 'First', FY: 2016 })); // 100 + 150 = 250

Javascript get value in json based on another value

I have a json similar to this one
{
"id": "1",
"month": "January",
"type": "inc",
"Value": "780.00",
"year": "2018",
},
{
"id": "2",
"month": "January",
"type": "inc",
"Value": "80.00",
"year": "2018",
},
{
"id": "3",
"month": "February",
"type": "inc",
"Value": "100.00",
"year": "2018",
},...
Now I need to get all the Value from the object for all the months, as you can see I may have more objects with the same month name. The closer I got to was creating 2 arrays 1 with the list of Months and 1 with the value but I got stuck, can someone lead me to the correct path?
The desired output would be to get an array like that ["January"=>1500, "February"=>2000...] or have 2 arrays, 1 with the list of months where there is income (I already have it) and the second the total income for these months, so it's like this: ["January", "February", "March"..] and the second one [1500, 2000, 300...]
You can use the function Array.prototype.reduce to sum each Value by month.
let arr = [{ "id": "1", "month": "January", "type": "inc", "Value": "780.00", "year": "2018", }, { "id": "2", "month": "January", "type": "inc", "Value": "80.00", "year": "2018", }, { "id": "3", "month": "February", "type": "inc", "Value": "100.00", "year": "2018", }],
result = arr.reduce((a, {month, Value}) => {
a[month] = (a[month] || 0) + +Value;
return a;
}, Object.create(null));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I actually can barely understand what you would like to achieve. Please provide some example.
If I understood you correctly, you can use map function of js array to map each object to its Value.
let arr = [...];
console.log(arr.map(item => item.Value));
You can do
var fabuaryDate = yourdata
.filter(function(data) { return data.month == "February" })
.map(function(x){return {value: x.Value} })
To get result in following format :
{
jan : [1,2,3],
feb : [3,4,5,6],
april : [3,4,5]
}
do this :
var output = {}
arr.forEach(element => {
if(!output[element.month]){
output[month] = new Array();
}
output[month].push(element.value);
});
You can iterate the object and fill an array with the values of the field you want to extract, like so:
const data = [ {
"id": "1",
"month": "January",
"type": "inc",
"Value": 780.00,
"year": "2018",
},
{
"id": "2",
"month": "January",
"type": "inc",
"Value": 80.00,
"year": "2018",
},
{
"id": "3",
"month": "February",
"type": "inc",
"Value": 100.00,
"year": "2018",
}];
let dataArray = data.reduce((accum, d) => {
if(!accum[d.month]) accum[d.month] = 0;
accum[d.month] += d.Value;
return accum;
},{});
console.log(dataArray);
Although you don't seem to be clear enough with what have you tried here is an example of what you could do in order to read all the values inside the json.
function myFunction(item) {
console.log(item.month + " with the value " + item.Value)
}
var jsonArray = [{"id": "1","month": "January", "type": "inc", "Value": "780.00", "year": "2018" }, { "id": "2", "month": "January", "type": "inc", "Value": "80.00", "year": "2018" }, { "id": "3", "month": "February", "type": "inc", "Value": "100.00", "year": "2018" }];
jsonArray.forEach(myFunction);
Since you're working with an array of objects you must access to each of the objects in the array and then get the attribute that you require.
Hope this help, have a great day.

creating different dataset array

I am trying to create different dataset based on month value. For eg. for June month one dataset and for July another dataset. But in my code, all the month values are getting combined and created as one dataset.
It will be really helpful who can help me in creating different dataset dynamically. I have attached the fiddle which I tried with my data object
JSFIDDLE
var obj = [{
date: "2017-06-01",
reqC: "129963",
month: "JUNE",
resC: "80522"
}, {
date: "2017-06-05",
reqC: "261162",
month: "JUNE",
resC: "83743"
},{
date: "2017-07-03",
reqC: "438860",
month: "JULY",
resC: "166107"
}]
var maindataset = [];
var dataset = [];
["reqC", "resC"].forEach((series) => {
dataset.push({
seriesname: series,
data: obj.map((el) => {
return el[series]
})
})
});
maindataset.push({
dataset: dataset
});
alert(JSON.stringify(maindataset));
// Expected Output
{
"dataset": [
{
"dataset": [ //June
{
"seriesname": "Req",
"data": [
{
"value": "129963"
},
{
"value": "261162"
}
]
},
{
"seriesname": "Res",
"data": [
{
"value": "80522"
},
{
"value": "83743"
}
]
}
]
},
{
"dataset": [ //July
{
"seriesname": "Req",
"data": [
{
"value": "438860"
}
]
},
{
"seriesname": "Res",
"data": [
{
"value": "166107"
}
]
}
]
}
]
}
You could use a nested hash table and iterate later the keys for the wanted parts.
var data = [{ date: "2017-06-01", reqC: "129963", month: "JUNE", resC: "80522" }, { date: "2017-06-05", reqC: "261162", month: "JUNE", resC: "83743" }, { date: "2017-07-03", reqC: "438860", month: "JULY", resC: "166107" }],
result = { dataset: [] },
parts = { reqC: 'Req', resC: 'Res' },
hash = { _: result.dataset };
data.forEach(function (a) {
var temp = hash;
if (!temp[a.month]) {
temp[a.month] = { _: [] };
temp._.push({ dataset: temp[a.month]._ });
}
temp = temp[a.month];
Object.keys(parts).forEach(function (k) {
if (!temp[k]) {
temp[k] = { _: [] };
temp._.push({ seriesname: parts[k], data: temp[k]._ });
}
temp[k]._.push({ value: a[k] });
});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can create groups based on month and then you can output the desired data structure. Check the snippet.
var obj = [{
date: "2017-06-01",
reqC: "129963",
month: "JUNE",
resC: "80522"
}, {
date: "2017-06-05",
reqC: "261162",
month: "JUNE",
resC: "83743"
},{
date: "2017-07-03",
reqC: "438860",
month: "JULY",
resC: "166107"
}];
var result = {};
var groups = obj.reduce(function(acc, obj) {
acc[obj.month] = acc[obj.month] || [];
acc[obj.month].push(obj);
return acc;
}, {});
//console.log(groups);
result.dataset = Object.keys(groups).map(function(key) {
return {
dataset: [{
"seriesname" : "Req",
"data": groups[key].map(function(o) {
return { value : o.reqC };
})
}, {
"seriesname" : "Res",
"data": groups[key].map(function(o) {
return { value : o.resC };
})
}]
};
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You cannot use the same property name for an object twice. You have an object in your data that looks like this:
"data": [
{
"value": "80522"
},
{
"value": "83743"
}
]
Either change the keys to unique ones:
"data": [
{
"value1": "80522"
},
{
"value2": "83743"
}
]
Or make it an array:
"data": [ "80522", "83743" ]
You need to add check for month as well.
Try this:
var obj = [{
date: "2017-06-01",
reqC: "129963",
month: "JUNE",
resC: "80522"
}, {
date: "2017-06-05",
reqC: "261162",
month: "JUNE",
resC: "83743"
},{
date: "2017-07-03",
reqC: "438860",
month: "JULY",
resC: "166107"
}]
var maindataset = [];
["JUNE","JULY"].forEach((month)=>{
var dataset = [];
["reqC", "resC"].forEach((series) => {
dataset.push({
seriesname: series,
data: obj.reduce((filtered, el) => {
if(el["month"] === month){
filtered.push({value: el[series]});
}
return filtered;
},[])
})
});
maindataset.push({
dataset: dataset
});
})
alert(JSON.stringify(maindataset));
output:
[{
"dataset": [{
"seriesname": "reqC",
"data": [{
"value": "129963"
}, {
"value": "261162"
}]
}, {
"seriesname": "resC",
"data": [{
"value": "80522"
}, {
"value": "83743"
}]
}]
}, {
"dataset": [{
"seriesname": "reqC",
"data": [{
"value": "438860"
}]
}, {
"seriesname": "resC",
"data": [{
"value": "166107"
}]
}]
}]

Converting an object to an array

I tried by using Object.keys() to convert the object
var obj1={
"jan": {
"COAL": "25"
},
"feb": {
"ROM": "50",
"WASTE": "55"
},
"april": {
"COAL": "60"
}
}
to
var obj2=[
{
"month": "jan",
"product": "COAL",
"quantity": "25"
},
{
"month": "feb",
"product": "ROM",
"quantity": "50"
},
{
"month": "feb",
"product": "WASTE",
"quantity": "55"
},
{
"month": "april",
"product": "COAL",
"quantity": "60"
}
]
but failed in the middle as I'm not able to calculate the properties say for example in "feb" there are two products "ROM" and "WASTE", but this can go upto 3 or 4. Can anyone please suggest possible solution for this problem?
This will do:
var res = []
for(i in obj1){
var rowObj = obj1[i];
for(j in rowObj){
var newObj = {'month' : i, 'product' : j, 'quantity' : rowObj[j]}
res.push(newObj);
}
}
console.log(res);
You need to loop over the keys in the outer object, then the keys in the inner objects, so as long as you can depend on ES5 Array methods:
var obj1={
"jan": {
"COAL": "25"
},
"feb": {
"ROM": "50",
"WASTE": "55"
},
"april": {
"COAL": "60"
}
}
var o = Object.keys(obj1).reduce(function(acc, month, i) {
Object.keys(obj1[month]).forEach(function(product) {
acc.push({'month':month, 'product':product, 'quantity':obj1[month][product]})
});
return acc;
}, []);
document.write(JSON.stringify(o));
Using ES6 arrow functions it becomes a little more concise:
var o = Object.keys(obj1).reduce((acc, m) => {
Object.keys(obj1[m]).forEach(p => acc.push({'month':m, 'product':p, 'quantity':obj1[m][p]}));
return acc;
}, []);

Categories

Resources