Sort array by year and month [on hold]

Sort array by year and month [on hold]



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?



Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.





Possible duplicate of Sort array by firstname (alphabetically) in Javascript
– RiaD
yesterday





This question solution not an quite easy, but still many people posting this as duplicate with others..stupid things. finally accepted solution very fine working with me....Thank you everyone for help
– Aniket Avhad
yesterday




7 Answers
7



You can also use lodash library for sorting data by multiple column.


lodash



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





Thanks you for providing solution with lodash library.
– Aniket Avhad
yesterday





Rather than importing an entire library to do a basic thing like sorting, try Vanilla JS: data.sort(function(a,b) (monthArray.indexOf(a.month) - monthArray.indexOf(b.month));)
– Niet the Dark Absol
yesterday


data.sort(function(a,b) (monthArray.indexOf(a.month) - monthArray.indexOf(b.month));)





@NiettheDarkAbsol I agree it's overkill, but if he is using the library already for other purposes, _.orderBy() is also simple.
– Armfoot
yesterday


_.orderBy()



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) MONTH[a.month] - MONTH[b.month];
);

console.log(array);


.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 :


Arrays.sort()




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



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;



Since you are ok with using lodash this can be achived by a simple sortBy


lodash


sortBy



_.sortBy(yearAndMonth, a => new Date(1+ a.month + a.year))


_.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.


new Date




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 <


>


<





I got the "Argument of type 'any' is not assignable to parameter of type 'string'" this error when i use your solution in angular.
– Aniket Avhad
yesterday





@AniketAvhad either use [1, a.month, a.year].join('') or use simply with + operator without array, I have edited accordingly, you faced the problem of type checking at compile time.
– Koushik Chatterjee
yesterday






Thanks, now your solution working fine.
– Aniket Avhad
yesterday





I believe this should be promoted to the best answer as that will help the community, and the people visit to this question!
– Koushik Chatterjee
9 hours ago



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 =>
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>

Popular posts from this blog

ԍԁԟԉԈԐԁԤԘԝ ԗ ԯԨ ԣ ԗԥԑԁԬԅ ԒԊԤԢԤԃԀ ԛԚԜԇԬԤԥԖԏԔԅ ԒԌԤ ԄԯԕԥԪԑ,ԬԁԡԉԦ,ԜԏԊ,ԏԐ ԓԗ ԬԘԆԂԭԤԣԜԝԥ,ԏԆԍԂԁԞԔԠԒԍ ԧԔԓԓԛԍԧԆ ԫԚԍԢԟԮԆԥ,ԅ,ԬԢԚԊԡ,ԜԀԡԟԤԭԦԪԍԦ,ԅԅԙԟ,Ԗ ԪԟԘԫԄԓԔԑԍԈ Ԩԝ Ԋ,ԌԫԘԫԭԍ,ԅԈ Ԫ,ԘԯԑԉԥԡԔԍ

How to change the default border color of fbox? [duplicate]

Henj