Reputation: 2185
I have many arrays of totals that correspond to a month represented by an integer for the last 180 days. For example:
[
{total: 54, month: 0},
{total: 55, month: 11},
{total: 74, month: 10},
{total: 21, month: 1},
{total: 36, month: 9},
{total: 98, month: 8},
{total: 55, month: 7},
]
I need to sort the elements in these arrays by month such that the most recent month comes first. For instance, [0, 11, 10, 1, 9, 8, 7]
should be sorted to [1, 0, 11, 10, 9, 8, 7]
(February, January, December, November, October, September, August.)
I'm using the following, which works well under conditions that roll over to the previous year:
> [0, 11, 10, 1, 9, 8, 7].sort((a, b) => Math.abs(a-b) > 6 ? a-b : b-a);
< [1, 0, 11, 10, 9, 8, 7] // good
However, it doesn't seem to work for this case:
> [11, 1, 0, 5, 4, 3, 2].sort((a, b) => Math.abs(a-b) > 6 ? a-b : b-a);
< [1, 0, 11, 5, 4, 3, 2] // should be [5, 4, 3, 2, 1, 0, 11]
If I change the condition to > 5
then it works, but breaks for another use case:
> [11, 1, 0, 5, 4, 3, 2].sort((a, b) => Math.abs(a-b) > 5 ? a-b : b-a);
< [5, 4, 3, 2, 1, 0, 11] // good
> [11, 10, 9, 8, 7, 1, 0].sort((a, b) => Math.abs(a-b) > 5 ? a-b : b-a);
< [11, 10, 9, 8, 7, 1, 0] // :-(
> [11, 10, 9, 8, 7, 1, 0].sort((a, b) => Math.abs(a-b) > 6 ? a-b : b-a);
< [1, 0, 11, 10, 9, 8, 7] // what I'd expect changing back to 6
My logic is that if the difference between two months is greater than six to sort them opposite than if the months are close together, or less than or equal to six. The length of the array can be between 1 and 7 (inclusive) and the months may not necessarily be sequential. Any help with my logic would be immensely appreciated!
Upvotes: 2
Views: 40
Reputation: 22247
Here's a way to sort the array based on what "this month" is.
var months = [11, 10, 9, 8, 7, 1, 0];
var thisMonth = 1; // get this from date object, eg
thisMonth += 12; // we want thisMonth - some month to be non-negative
months.sort((a, b) => {
return (thisMonth - a) % 12 - (thisMonth - b) % 12;
});
console.log(months);
Upvotes: 3
Reputation: 386654
You could sort with an offset and modulo for moving the start value of sorting.
const sort = month => (a, b) => (b.month + 12 - month) % 12 - (a.month + 12 - month) % 12;
var data = [{ total: 54, month: 0 }, { total: 55, month: 11 }, { total: 74, month: 10 }, { total: 21, month: 1 }, { total: 36, month: 9 }, { total: 98, month: 8 }, { total: 55, month: 7 }];
console.log(data.sort(sort(1))); // 0 11 10 9 8 7 1
console.log(data.sort(sort(8))); // 7 1 0 11 10 9 8
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1