问题
This will sound as an easy problem but I spent my Sunday trying to figure out what's wrong with my implementation described below so I am posting it to SO as a last resort.
I have a javascript application that receives data structures from a server. The server side sends the data unsorted for performance reasons.
Here is a snippet of the the javascript code receiving data:
var seriesRawDataArray = ko.observableArray();
...
analyticscontext.series(seriesRawDataArray).done(function () {
renderSeries();
});
The analyticscontext module queries the data using ajax:
function series(seriesData) {
return $.ajax({
url: "/api/analytics/series",
type: "GET",
success: function (data) {
return seriesData(data);
}
});
}
The renderSeries performs a sort on the data before rendering it:
// Sort the data by date using moment.js
seriesRawDataArray.sort(function (left, right) {
var leftDate = moment.utc(left.timeStamp);
var rightDate = moment.utc(right.timeStamp);
var diff = leftDate.diff(rightDate);
return diff > 0;
});
PROBLEM
Here is a data sample I receive from my server:
Notice the unsorted items at the end.
the seriesRawDataArray.sort seem to have no effect on the original array which does not get sorted no matter what I change in the sorting method. The output is always:
Notice the unsorted elements here. The libraries I am using and the data is definitely not the problem as this jsfiddle works just fine! Is there something wrong with this code?
回答1:
short answer
You should return the difference between the two dates, not a boolean:
// sort the data by date using moment.js
seriesRawDataArray.sort(function (left, right) {
return moment.utc(left.timeStamp).diff(moment.utc(right.timeStamp))
});
why
Array.prototype.sort expects a negative, zero, or positive value to be returned. Generally, you'll write a sort function like this:
yourArray.sort(function (a, b) {
if (a < b) { // a comes first
return -1
} else if (b < a) { // b comes first
return 1
} else { // equal, so order is irrelevant
return 0 // note: sort is not necessarily stable in JS
}
})
The anonymous function passed to sort serves as the comparator for the native implementation of the sort function.
However, your negative value doesn't have to be -1 and your positive value doesn't have to be +1. Therefore, when sorting numbers, you can instead use the shortcut:
yourArray.sort(function (a, b) {
return a - b
})
In JavaScript, subtracting two dates coerces them both into numbers, which is why we could use return moment.utc(left.timeStamp).diff(moment.utc(right.timeStamp))
(instead of direct subtraction -, this method uses moment.prototype.diff from the moment.js library)
However, in your code, you returned diff > 0, which can be either true or false. Because of type coercion, JavScript will read true as 1 and false as 0. This means your sort function will never return -1. Therefore, your elements will not be sorted correctly.
回答2:
let sortedDates = dates.sort(function(a, b){
return moment(b).format('X')-moment(a).format('X')
});
Since moment can format valid dates the best way is to use the sort method javascript, so when formatting the date to timestamp, basically you sort by number.
References:
http://www.momentjs.com/docs/#/displaying/format
http://www.w3schools.com/jsref/jsref_sort.asp
来源:https://stackoverflow.com/questions/28013045/sort-array-by-date-gives-unexpected-results