JS group by month/year of date - javascript

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/

Related

Merge array of an object based on a common field

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);

how could i change the string data format ..?

The data format, which I get from back-end is
{
"2020-08-22": 1425,
"2020-08-23": 1475,
"2020-08-24": 1475,
"flightnumber": "EK-853",
"source": "emirates",
"stops": "stops-0"
}
Is that possible to change the key data as following
{
"Aug 22": 1425,
"Aug 23": 1475,
"Aug 24": 1475,
"flightnumber": "EK-853",
"source": "emirates",
"stops": "stops-0"
}
Please tell me some solution for this.
Below snippet could help you. It has several things to notice:
iterate through object's keys
object's dynamic key
detect invalid date
const data = {
"2020-08-22": 1425,
"2020-08-23": 1475,
"2020-08-24": 1475,
flightnumber: "EK-853",
source: "emirates",
stops: "stops-0",
}
const monthNames = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
]
const res = {}
Object.keys(data).forEach((k) => {
const date = new Date(k)
if (!isNaN(date.getTime())) {
res[`${monthNames[date.getMonth()]} ${date.getDate()}`] = data[k]
} else {
res[k] = data[k]
}
})
console.log(res)

Mapping object to array in js

I am beginner in data structure and trying to improve my skills.
I am trying to divide the object value to list of other object.
So I/P is
1st Object JSON:
let mapMonth ={
"10": 8,
"11": 30,
"12": 31,
"01": 23
}
where 10 is Oct, 11 is Nov, 12 is Dec and 01 is Jan.
2nd Object JSON:
let mapData = {
"key1": {
"subkey1": [
[407341537, 1666737463, 363248139, 596560162]
],
"subkey2": ["Oct", "Nov", "Dec", "Jan"]
},
"key2": {
"subkey1": [
[78491802, 334718068, 68299710, 81365082]
],
"subkey2": ["Oct", "Nov", "Dec", "Jan"]
},
"key3": {
"subkey1": [
[501844, 3362217, 648527, 1073573]
],
"subkey2": ["Oct", "Nov", "Dec", "Jan"]
}
}
So now I need to divide 407341537 with 8 i.e 50917692.125, 1666737463 with 30 i.e 55557915.4333 and so on..
Expected output:
{
"key1": {
"subkey1": [
[50917692.125, 55557915.4333, 11717681.9,72466846.2174]
],
"subkey2": ["Oct", "Nov", "Dec", "Jan"]
},
"key2": {
"subkey1": [
[9811475.25, 11157268.9333, 2203216.45161, 3537612.26087]
],
"subkey2": ["Oct", "Nov", "Dec", "Jan"]
},
"key3": {
"subkey1": [
[62730.5, 112073.9, 20920.225, 46677.086]
],
"subkey2": ["Oct", "Nov", "Dec", "Jan"]
}
}
Code I have tried:
let averageObj = {};
var count = 0;
for (let key in mapData) {
averageObj[key] = [];
mapData[key]['subkey1'][0].forEach((data, index) => {
for (let monthKey in mapMonth) {
averageObj[key].push(data / mapMonth[monthKey]);
}
});
}
Please let me know if you need anything else.
Assuming an object with fixed keys and nested array with only one index:
This approach mutates the original object.
let mapMonthDesc = {"Oct": "10","Nov": "11","Dec": "12","Jan": "01"},
mapMonth = {"10": 8,"11": 30,"12": 31,"01": 23},
mapData = {"key1": {"subkey1": [[407341537, 1666737463, 363248139, 596560162]],"subkey2": ["Oct", "Nov", "Dec", "Jan"]},"key2": {"subkey1": [[78491802, 334718068, 68299710, 81365082]],"subkey2": ["Oct", "Nov", "Dec", "Jan"]},"key3": {"subkey1": [[501844, 3362217, 648527, 1073573]],"subkey2": ["Oct", "Nov", "Dec", "Jan"]}};
Object.values(mapData).forEach(({subkey1: [numbers], subkey2}) => {
numbers.forEach((n, i) => numbers[i] = n / mapMonth[mapMonthDesc[subkey2[i]]]);
});
console.log(mapData);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

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"
}]
}]
}]

Categories

Resources