Sort array by year and month [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have the array as below,
let  yearAndMonth  =  [
{ "year": 2013, "month": "FEBRUARY" },
{ "year": 2015, "month": "MARCH" },
{ "year": 2013, "month": "JANUARY" },
{ "year": 2015, "month": "FEBRUARY" }
]
I want to sort the array by year first and after that sort month from the year,
I want the output like this,
yearAndMonth  =  [
{ "year": 2013, "month": "JANUARY " },
{ "year": 2013, "month": "FEBRUARY" },
{ "year": 2015, "month": "FEBRUARY" },
{ "year": 2015, "month": "MARCH" }
]
How to achieve this?

You could take an object for the month names and their numerical value.
The chain the order by taking the delta of year and month.
var array = [{ year: 2013, month: "FEBRUARY" }, { year: 2015, month: "MARCH" }, { year: 2013, month: "JANUARY" }, { year: 2015, month: "FEBRUARY" }];
array.sort(function (a, b) {
var MONTH = { JANUARY: 0, FEBRUARY: 1, MARCH: 2, APRIL: 3, MAY: 4, JUNE: 5, JULY: 6, AUGUST: 7, SEPTEMBER: 8, OCTOBER: 9, NOVEMBER: 10, DECEMBER: 11 };
return a.year - b.year || MONTH[a.month] - MONTH[b.month];
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can create an array for months names and sort like this:
let data = [
{ "year": 2013, "month": "FEBRUARY" }, { "year": 2015, "month": "MARCH" },
{ "year": 2013, "month": "JANUARY" }, { "year": 2015, "month": "FEBRUARY" }
];
let months = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
data.sort(
(a, b) => (a.year - b.year) || (months.indexOf(a.month) - months.indexOf(b.month))
);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can make a map which maps the Month to the month number and then use Arrays.sort() with your own custom comparator :
let months = { 'JANUARY' : 1, 'FEBRUARY' : 2, 'MARCH' : 3, 'APRIL' : 4, 'MAY' : 5, 'JUNE' : 6, 'JULY' : 7, 'AUGUST' : 8, 'SEPTEMBER' : 9, 'OCTOBER' : 10, 'NOVEMBER' : 11, 'DECEMBER' : 12 };
let yearAndMonth = [ { "year": 2013, "month": "FEBRUARY" }, { "year": 2015, "month": "MARCH" }, { "year": 2013, "month": "JANUARY" }, { "year": 2015, "month": "FEBRUARY" } ];
yearAndMonth.sort((a,b)=> a.year - b.year || months[a.month.toUpperCase()] - months[b.month.toUpperCase()]);
console.log(yearAndMonth);

Since you are ok with using lodash this can be achived by a simple sortBy
_.sortBy(yearAndMonth, a => new Date(1+ a.month + a.year))
It will construct a new Date for each month and year (with date 1) and that should work the way you want.
let yearAndMonth = [
{ "year": 2013, "month": "FEBRUARY" },
{ "year": 2015, "month": "MARCH" },
{ "year": 2013, "month": "JANUARY" },
{ "year": 2015, "month": "FEBRUARY" }
]
let res = _.sortBy(yearAndMonth, a => new Date(1 + a.month + a.year));
console.log('Sorted Result: ', res);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Note: You do not need to have array/object/map of all the months for this to have a look up to perform > or <

You can also use lodash library for sorting data by multiple column.
I have created a demo on Stackblitz. I hope this will help/guide to you/others.
lodash - Documentation
Component.html
<table width="100%">
<tr>
<td>Year</td>
<td>Month</td>
</tr>
<tr *ngFor="let datas of sortedData">
<td>{{datas.year}}</td>
<td>{{datas.month}}</td>
</tr>
</table>
Component.ts
sortedData: any[];
data = [
{ "year": 2013, "month": "FEBRUARY" },
{ "year": 2015, "month": "MARCH" },
{ "year": 2013, "month": "JANUARY" },
{ "year": 2013, "month": "MARCH" },
{ "year": 2013, "month": "APRIL" },
{ "year": 2015, "month": "FEBRUARY" }
];
monthArray: any = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
ngOnInit() {
this.sortedData = _.orderBy(data, [(datas) => datas.year, (user) => (this.monthArray.indexOf(user.month))], ["asc", "asc"]);
console.log(this.sortedData);
}

Declaring the month names in an array to get the relative value of the month string when comparing with each other.
First comparison will be on the year, if both the year values are same then proceeding with the month comparison based on the months array created.
let months = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
yearAndMonth.sort((a,b) =>{
if(a.year > b.year) return 1;
else if(a.year < b.year) return -1;
else {
if(months.indexOf(a.month.toUpperCase()) >
months.indexOf(b.month.toUpperCase()))
return 1;
else if(months.indexOf(a.month.toUpperCase()) <
months.indexOf(b.month.toUpperCase()))
return -1
else return 0;
}
});

See also: JsFiddle
Allow me to provide a plain ES version (sort array of objects on 1 or more key values, serial dependant (sort on 1, sort 2 within 1, sort on 3 within 1 and 2 etc.), non mutating, i.e. keep the original array as is):
const log = (...str) =>
document.querySelector("pre").textContent += `${str.join("\n")}\n`;
const data = getData();
const xSort = XSort();
const months = [ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ];
log( JSON.stringify(
xSort
.create(data)
.orderBy( {key: "year"}, { key: v => months.indexOf(v.month) } ),
null,
" ")
);
function XSort() {
const multiSorter = sortKeys => {
if (!sortKeys || sortKeys[0].constructor !== Object) {
throw new TypeError("Provide at least one {key: [keyname]} to sort on");
}
return function (val0, val1) {
for (let sortKey of sortKeys) {
const v0 = sortKey.key instanceof Function ? sortKey.key(val0) : val0[sortKey.key];
const v1 = sortKey.key instanceof Function ? sortKey.key(val1) : val1[sortKey.key];
const isString = v0.constructor === String || v1.constructor === String;
const compare = sortKey.descending ?
isString ? v1.toLowerCase().localeCompare(v0.toLowerCase()) : v1 - v0 :
isString ? v0.toLowerCase().localeCompare(v1.toLowerCase()) : v0 - v1;
if (compare !== 0) {
return compare;
}
}
};
}
const Sorter = function (array) {
this.array = array;
};
Sorter.prototype = {
orderBy: function(...sortOns) {
return this.array.slice().sort(multiSorter(sortOns));
},
};
return {
create: array => new Sorter(array)
};
}
function getData() {
return [{
"year": 2013,
"month": "FEBRUARY",
},
{
"year": 2015,
"month": "MARCH",
},
{
"year": 2015,
"month": "SEPTEMBER",
},
{
"year": 2013,
"month": "JANUARY",
},
{
"year": 2013,
"month": "MARCH",
},
{
"year": 2013,
"month": "APRIL",
},
{
"year": 2015,
"month": "FEBRUARY",
}
];
}
<pre></pre>

Related

Compare common columns from two list and create a new list according with the match and mismatch

this.monthList.map(sli_record => {
let rec_found = this.newlist.find(vale_record =>vale_record.Value === sli_record.Value);
if(rec_found) {
this.Results['Value'] = sli_record['Value'];
this.Results['Month'] = sli_record['Month'];
this.Results['Year'] = sli_record['Year'];
this.Results['IsSubmittedID'] = sli_record['IsSubmittedID'];
this.Results['IsEligible'] = sli_record['IsEligible'];
this.Results['BackgroundCheckdone'] = sli_record['BackgroundCheckdone'];
}
else {
this.Results['Value'] = sli_record['Value'];
this.Results['Month'] = sli_record['Month'];
this.Results['Year'] = sli_record['Year'];
this.Results['IsSubmittedID'] = 0;
this.Results['IsEligible'] = 0;
this.Results['BackgroundCheckdone'] = 0;
this.Results['UserPass'] = sli_record['UserPass'];
}
//console.log(this.Results);
return this.Results;
}
Hi I am trying to check a common value tag of one list against another and fill in the data to a new list new list "Results" according to the conditional check but not able to generate the desired result.
Whenever the column "Value" from newlist is compared with the "Value" of monthList, if there is no value exist for that particular entry(Value column of newlist) in the monthList then it should create a entry with default values in the newlist array
for eg: Consider this value
{Id: 3, Value: 'June 2022'}
this does not exist on the newlist as of now but it should add an new entry like below to the newlist array
{
"Value": "June 2022",
"Month": "June",
"Year": 2022,
"IsSubmittedID": 0,
"IsEligible": 0,
"BackgroundCheckdone": 0
}
newlist=[
{ Id: 0,
Month: 'May',
Year: 2022,
Value: 'February 2022',
IsSubmittedID: 0,
IsEligible: 1,
BackgroundCheckdone: 1,
},
{Id: 0,
Month: 'July',
Year: 2022,
Value: 'July 2022',
IsSubmittedID: 0,
IsEligible: 1,
BackgroundCheckdone: 1,
}]
monthList =[
{Id: 1, Value: 'August 2022'}
{Id: 2, Value: 'July 2022'}
{Id: 3, Value: 'June 2022'}
{Id: 4, Value: 'May 2022'}
{Id: 5, Value: 'April 2022'}]
**I should get my result as of below for the Results list not able to figure out how to bind the value for the according to the list**
[
{
"Value": "August 2022",
"Month": "August",
"Year": 2022,
"IsSubmittedID": 0,
"IsEligible": 0,
"BackgroundCheckdone": 0
},
{
"Value": "July 2022",
"Month": "July",
"Year": 2022,
"IsSubmittedID": 0,
"IsEligible": 1,
"BackgroundCheckdone": 1
},
{
"Value": "June 2022",
"Month": "June",
"Year": 2022,
"IsSubmittedID": 0,
"IsEligible": 0,
"BackgroundCheckdone": 0
},
{
"Value": "May 2022",
"Month": "May",
"Year": 2022,
"IsSubmittedID": 1,
"IsEligible": 1,
"BackgroundCheckdone": 1
}
]

Change object label on specific value in js

I'm working on charts in React.js and i want to display data sorted by month. In django i've created view for displaying json with total events per month and it looks like this:
[
{
"month": "2022-06-01T00:00:00+02:00",
"total": 4
},
{
"month": "2022-08-01T00:00:00+02:00",
"total": 1
}
]
]
I would like to sort every object in that array and change value 'month' from numbers to month name, so it would be:
[
{
"month": "june",
"total": 4
},
{
"month": "august",
"total": 1
}
]
]
For generating charts i'm using chartist.
You could store the full date as a seperate key (called date), and set the month in a seperate function using a predefined array for the names of each month. Here is the code you would use:
const monthName = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"]; // Array representing each month
var chartItems = [
{
"date": "2022-06-01T00:00:00+02:00",
"month": null,
"total": 4
},
{
"date": "2022-08-01T00:00:00+02:00",
"month": null,
"total": 1
}
];
// Run through each item in the array
function setMonths(arr) {
arr.forEach(item => {
const date = new Date(item.date); // Convert date string to Date object
const monthIndex = date.getMonth(); // Get index of month from the Date
const month = monthName[monthIndex]; // Convert index into text representing the month
item.month = month; // Set the month key in the object to the new month
});
}
setMonths(chartItems); // Call function to set months in the array
As an alternative, you could also make a method for each object in the array that gets the month, but you would need to run this everytime you want to get the month. Here is the code for that:
const monthName = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
var chartItems = [
{
"date": "2022-06-01T00:00:00+02:00",
"month": function() { return monthName[new Date(this.date).getMonth()]; },
"total": 4
},
{
"date": "2022-08-01T00:00:00+02:00",
"month": function() { return monthName[new Date(this.date).getMonth()]; },
"total": 1
}
];
And you would get it like this:
chartItems[0].month(); // "[0]", meaning the first item in the array

How to replace object A to B in an arrays if the object A got same property in object B [duplicate]

This question already has answers here:
Replacing objects in array
(17 answers)
Closed 3 years ago.
I'm trying to get an array from two different arrays. I'm not sure how to do it with ES6.
I want the current_year_data is replacing to previous_year_data
The First array is:
let previous_year_data = [
{ month: "January", value: 300 },
{ month: "February", value: 1 },
{ month: "March", value: 2 },
{ month: "April", value: 3 },
{ month: "May", value: 4 },
{ month: "Jun", value: 5 },
{ month: "July", value: 6 },
{ month: "August", value: 7 },
{ month: "September", value: 8 },
{ month: "October", value: 9 },
{ month: "November", value: 10 },
{ month: "December", value: 11 },
];
Second array:
let current_year_data = [
{ month: "January", value: 4459 }
];
The result should be in:
let current_year_data = [
{ month: "January", value: 4459 },
{ month: "February", value: 1 },
{ month: "March", value: 2 },
{ month: "April", value: 3 },
{ month: "May", value: 4 },
{ month: "Jun", value: 5 },
{ month: "July", value: 6 },
{ month: "August", value: 7 },
{ month: "September", value: 8 },
{ month: "October", value: 9 },
{ month: "November", value: 10 },
{ month: "December", value: 11 },
];
Thanks
It is possible to use map method. In addition, you can use Map collection to have O(1) of access to elements items when you map your array:
let unique = new Map(current_year_data.map(s=> [s.month, s.value]))
previous_year_data.map(({month, value})=> ({month, value: unique.get(month) || value }));
An example:
let previous_year_data = [
{ month: "January", value: 300 },
{ month: "February", value: 1 },
{ month: "March", value: 2 },
{ month: "April", value: 3 },
{ month: "May", value: 4 },
{ month: "Jun", value: 5 },
{ month: "July", value: 6 },
{ month: "August", value: 7 },
{ month: "September", value: 8 },
{ month: "October", value: 9 },
{ month: "November", value: 10 },
{ month: "December", value: 11 },
];
let current_year_data = [
{ month: "January", value: 4459 }
];
let unique = new Map(current_year_data.map(s=> [s.month, s.value]))
const result = previous_year_data.map(({month, value})=>
({month, value: unique.get(month) || value }));
console.log(result)
For such requirements, combine or merge JSON arrays unique by the key will work! See the following:
// Note: this will pick the last duplicated item in the list.
const previous_year_data = [
{ month: "January", value: 300 },
{ month: "February", value: 1 },
{ month: "March", value: 2 },
{ month: "April", value: 3 },
{ month: "May", value: 4 },
{ month: "Jun", value: 5 },
{ month: "July", value: 6 },
{ month: "August", value: 7 },
{ month: "September", value: 8 },
{ month: "October", value: 9 },
{ month: "November", value: 10 },
{ month: "December", value: 11 },
];
const current_year_data = [
{ month: "January", value: 4459 }
];
const key = 'month'; //Replace this key with unique key
const result = [...new Map([...previous_year_data, ...current_year_data].map(item =>
[item[key], item])).values()];
console.log(result);
/*OUTPUT
[
{
"month": "January",
"value": 4459
},
{
"month": "February",
"value": 1
},
{
"month": "March",
"value": 2
},
{
"month": "April",
"value": 3
},
{
"month": "May",
"value": 4
},
{
"month": "Jun",
"value": 5
},
{
"month": "July",
"value": 6
},
{
"month": "August",
"value": 7
},
{
"month": "September",
"value": 8
},
{
"month": "October",
"value": 9
},
{
"month": "November",
"value": 10
},
{
"month": "December",
"value": 11
}
]
*/

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.

How to flatten JSON result from aggregation output in above query

I am trying this mongo aggregation I got the output but my required output is not getting anyone please suggest my problem
const monthsEnum = {
"_id": "year",
"1": "January",
"2": "February",
"3": "March",
"4": "April",
"5": "May",
"6": "June",
"7": "July",
"8": "August",
"9": "September",
"10": "October",
"11": "November",
"12": "December"
};
Light.aggregate([
{ "$match": {
"CREATE_DATE": {
"$lte": new Date(),
"$gte": new Date(new Date().setDate(new Date().getDate()-120))
}
} },
{ "$group": {
"_id": {
"month": { "$month": "$CREATE_DATE" },
"year": { "$year": "$CREATE_DATE" }
},
"avgofozone": { "$avg": "$OZONE" }
} },
{ "$group": {
"_id": "$year",
"avgs": {
"$push": {
"k": { "$substr": ["$month", 0, -1 ] },
"v": "$avgofozone"
}
}
} },
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{ "$arrayToObject": "$avgs" },
"$$ROOT"
]
}
} },
{ "$project": { "avgs": 0 } }
], (err, data) => {
console.log("naresh:" +JSON.stringify(data));
const polute = Object.keys(data).reduce((p, c) => ({...p, monthsEnum[c]: data[c]}), {});
res.json(polute);
})
output:
[
{
"zone_type": "avgofozone",
"year": 2018,
"February": 21.07777777777778,
"March": 17.8,
"January": 17.8
}
]
MY expected output is:
zone_type year February March January
avgofozone 2018 21.07777777777778 17.8 17.8

Categories

Resources