web-dev-qa-db-fra.com

Le tableau de tri par date donne des résultats inattendus

Cela semblera être un problème facile, mais j'ai passé mon dimanche à essayer de comprendre ce qui ne va pas avec mon implémentation décrite ci-dessous, donc je le poste sur SO en dernier recours.

J'ai une application javascript qui reçoit des structures de données d'un serveur. Le côté serveur envoie les données non triées pour des raisons de performances.

Voici un extrait du code javascript recevant les données:

    var seriesRawDataArray = ko.observableArray();
    ...
    analyticscontext.series(seriesRawDataArray).done(function () {
        renderSeries();
    });

Le module analyticscontext interroge les données en utilisant ajax:

function series(seriesData) {
    return $.ajax({
        url: "/api/analytics/series",
        type: "GET",
        success: function (data) {
            return seriesData(data);
        }
    });
}

renderSeries effectue un tri sur les données avant de les rendre:

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

Problème [~ # ~] [~ # ~]

Voici un échantillon de données que je reçois de mon serveur: enter image description here

Remarquez les articles non triés à la fin. le seriesRawDataArray.sort semble n'avoir aucun effet sur le tableau d'origine qui n'est pas trié quoi que je change dans la méthode de tri. La sortie est toujours:

enter image description here

Notez les éléments non triés ici. Les bibliothèques que j'utilise et les données ne sont certainement pas le problème car cela jsfiddle fonctionne très bien! Y a-t-il un problème avec ce code?

28
GETah

réponse courte

Vous devez renvoyer la différence entre les deux dates, pas un booléen:

// sort the data by date using moment.js
seriesRawDataArray.sort(function (left, right) {
    return moment.utc(left.timeStamp).diff(moment.utc(right.timeStamp))
});

pourquoi

Array.prototype.sort s'attend à ce qu'une valeur négative, nulle ou positive soit renvoyée. Généralement, vous écrirez une fonction de tri comme celle-ci:

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

La fonction anonyme passée à sort sert de comparateur pour l'implémentation native de la fonction sort.

Cependant, votre valeur négative ne doit pas nécessairement être -1 Et votre valeur positive ne doit pas être +1. Par conséquent, lors du tri des nombres, vous pouvez utiliser à la place le raccourci:

yourArray.sort(function (a, b) {
    return a - b
})

En JavaScript, la soustraction de deux dates les contraint à la fois en nombres, c'est pourquoi nous pourrions utiliser return moment.utc(left.timeStamp).diff(moment.utc(right.timeStamp))

(au lieu de la soustraction directe -, cette méthode utilise moment.prototype.diff de la bibliothèque moment.js)

Cependant , dans votre code, vous avez renvoyé diff > 0, Qui peut être true ou false . En raison de la contrainte de type, JavScript lira true comme 1 Et false comme 0. Cela signifie que votre fonction de tri ne renverra jamais -1. Par conséquent, vos éléments ne seront pas triés correctement.

130
royhowie
let _sortedDates = dates.sort(function(a, b){
  return moment(b).format('X')-moment(a).format('X')
});

Étant donné que moment peut formater des dates valides, la meilleure façon est d'utiliser la méthode de tri javascript, donc lors du formatage de la date en horodatage, vous triez essentiellement par numéro.

Références: momentjs.com/docs/#/displaying/format, w3schools.com/jsref/jsref_sort.asp

4
Ylli Gashi