Tri des objets par valeurs de propriété

88

Comment implémenter le scénario suivant en utilisant uniquement Javascript:

  • Créez un objet voiture avec des propriétés (vitesse maximale, marque, etc.)
  • Trier une liste de voitures classées par ces propriétés
Constructeur
la source
3
@durilai: JavaScript est orienté objet, le modèle OO de JavaScript est basé sur le prototypage et est vraiment, vraiment polyvalent ... en.wikipedia.org/wiki/Prototype-based_programming
Christian C. Salvadó
Je recommande d'utiliser lodash.js: lodash.com/docs#sortBy
Chemical Programmer

Réponses:

159

javascript a la fonction de tri qui peut prendre une autre fonction comme paramètre - cette seconde fonction est utilisée pour comparer deux éléments.

Exemple:

cars = [

    {
        name: "Honda",
        speed: 80
    },

    {
        name: "BMW",
        speed: 180
    },

    {
        name: "Trabi",
        speed: 40
    },

    {
        name: "Ferrari",
        speed: 200
    }
]


cars.sort(function(a, b) { 
    return a.speed - b.speed;
})

for(var i in cars)
    document.writeln(cars[i].name) // Trabi Honda BMW Ferrari 

ok, d'après votre commentaire, je vois que vous utilisez le mot «trier» dans un mauvais sens. Dans la programmation, «trier» signifie «mettre les choses dans un certain ordre», pas «organiser les choses en groupes». Ce dernier est beaucoup plus simple - c'est ainsi que vous «triez» les choses dans le monde réel

  • créer deux tableaux vides ("boîtes")
  • pour chaque objet de votre liste, vérifiez s'il correspond aux critères
  • si oui, mettez-le dans la première "case"
  • si non, mettez-le dans la deuxième "case"
user187291
la source
10
Note simple pour plus de commodité: this ( a.someProp - b.someProp) trie du plus bas au plus élevé , et l'inverse ( b.someProp - a.someProp) trie du plus élevé au plus bas. Fondamentalement, si la fonction renvoie moins de 0, a vient avant b.
user56reinstatemonica8
Notez également que cette solution ne fonctionne que lorsque les propriétés que vous triez sont des nombres. Cela fonctionne dans l'exemple pour le tri par vitesse maximale, mais si vous souhaitez trier par marque de voiture, cette solution ne triera pas les chaînes par ordre alphabétique. Cheeso fournit une réponse pour le tri à la fois par des nombres et des chaînes.
Cole Marshall
23

Exemple.

Cela fonctionne sur cscript.exe, sous Windows.

// define the Car class
(function() {
    // makeClass - By John Resig (MIT Licensed)
    // Allows either new User() or User() to be employed for construction.
    function makeClass(){
        return function(args){
            if ( this instanceof arguments.callee ) {
                if ( typeof this.init == "function" )
                    this.init.apply( this, (args && args.callee) ? args : arguments );
            } else
                return new arguments.callee( arguments );
        };
    }

    Car = makeClass();

    Car.prototype.init = function(make, model, price, topSpeed, weight) {
        this.make = make;
        this.model = model;
        this.price = price;
        this.weight = weight;
        this.topSpeed = topSpeed;
    };
})();


// create a list of cars
var autos = [
    new Car("Chevy", "Corvair", 1800, 88, 2900),
    new Car("Buick", "LeSabre", 31000, 138, 3700),
    new Car("Toyota", "Prius", 24000, 103, 3200),
    new Car("Porsche", "911", 92000, 155, 3100),
    new Car("Mercedes", "E500", 67000, 145, 3800),
    new Car("VW", "Passat", 31000, 135, 3700)
];

// a list of sorting functions
var sorters = {
    byWeight : function(a,b) {
        return (a.weight - b.weight);
    },
    bySpeed : function(a,b) {
        return (a.topSpeed - b.topSpeed);
    },
    byPrice : function(a,b) {
        return (a.price - b.price);
    },
    byModelName : function(a,b) {
        return ((a.model < b.model) ? -1 : ((a.model > b.model) ? 1 : 0));
    },
    byMake : function(a,b) {
        return ((a.make < b.make) ? -1 : ((a.make > b.make) ? 1 : 0));
    }
};

function say(s) {WScript.Echo(s);}

function show(title)
{
    say ("sorted by: "+title);
    for (var i=0; i < autos.length; i++) {
        say("  " + autos[i].model);
    }
    say(" ");
}

autos.sort(sorters.byWeight);
show("Weight");

autos.sort(sorters.byModelName);
show("Name");

autos.sort(sorters.byPrice);
show("Price");

Vous pouvez également créer un trieur général.

var byProperty = function(prop) {
    return function(a,b) {
        if (typeof a[prop] == "number") {
            return (a[prop] - b[prop]);
        } else {
            return ((a[prop] < b[prop]) ? -1 : ((a[prop] > b[prop]) ? 1 : 0));
        }
    };
};

autos.sort(byProperty("topSpeed"));
show("Top Speed");
Cheeso
la source
13

J'ai écrit cette fonction simple pour moi-même:

function sortObj(list, key) {
    function compare(a, b) {
        a = a[key];
        b = b[key];
        var type = (typeof(a) === 'string' ||
                    typeof(b) === 'string') ? 'string' : 'number';
        var result;
        if (type === 'string') result = a.localeCompare(b);
        else result = a - b;
        return result;
    }
    return list.sort(compare);
}

par exemple vous avez une liste de voitures:

var cars= [{brand: 'audi', speed: 240}, {brand: 'fiat', speed: 190}];
var carsSortedByBrand = sortObj(cars, 'brand');
var carsSortedBySpeed = sortObj(cars, 'speed');
slavugan
la source
6

Disons que nous devons trier une liste d'objets dans l'ordre croissant en fonction d'une propriété particulière, dans cet exemple, disons que nous devons trier en fonction de la propriété "name", puis ci-dessous est le code requis:

var list_Objects = [{"name"="Bob"},{"name"="Jay"},{"name"="Abhi"}];
Console.log(list_Objects);   //[{"name"="Bob"},{"name"="Jay"},{"name"="Abhi"}]
    list_Objects.sort(function(a,b){
        return a["name"].localeCompare(b["name"]); 
    });
Console.log(list_Objects);  //[{"name"="Abhi"},{"name"="Bob"},{"name"="Jay"}]
Jayanth G
la source
1
Je pense que vous avez une faute de frappe? renvoie un ["nom"]. localeCompare (b. ["nom"]); devrait être return a ["name"]. localeCompare (b ["name"]); (supprimer le. après b)
Little Brain
3

Avec les fonctions fléchées ES6, ce sera comme ceci:

//Let's say we have these cars
let cars = [ { brand: 'Porsche', top_speed: 260 },
  { brand: 'Benz', top_speed: 110 },
  { brand: 'Fiat', top_speed: 90 },
  { brand: 'Aston Martin', top_speed: 70 } ]

Array.prototype.sort() peut accepter une fonction de comparateur (ici j'ai utilisé la notation fléchée, mais les fonctions ordinaires fonctionnent de la même manière):

let sortedByBrand = [...cars].sort((first, second) => first.brand > second.brand)

// [ { brand: 'Aston Martin', top_speed: 70 },
//   { brand: 'Benz', top_speed: 110 },
//   { brand: 'Fiat', top_speed: 90 },
//   { brand: 'Porsche', top_speed: 260 } ]

L'approche ci-dessus copie le contenu du tableau de voitures dans un nouveau et le trie par ordre alphabétique en fonction des noms de marque. De même, vous pouvez passer une fonction différente:

let sortedBySpeed =[...cars].sort((first, second) => first.top_speed > second.top_speed)

//[ { brand: 'Aston Martin', top_speed: 70 },
//  { brand: 'Fiat', top_speed: 90 },
//  { brand: 'Benz', top_speed: 110 },
//  { brand: 'Porsche', top_speed: 260 } ]

Si cela ne vous dérange pas, la mutation du tableau original cars.sort(comparatorFunction)fera l'affaire.

Vertige de Farzad
la source
3

Voici un court exemple qui crée un tableau d'objets et les trie par ordre numérique ou alphabétique:

// Create Objects Array

var arrayCarObjects = [
{brand: "Honda",        topSpeed: 45},
{brand: "Ford",         topSpeed: 6},
{brand: "Toyota",       topSpeed: 240},
{brand: "Chevrolet",    topSpeed: 120},
{brand: "Ferrari",      topSpeed: 1000}
];

// Sort Objects Numerically

arrayCarObjects.sort((a, b) => (a.topSpeed - b.topSpeed));

// Sort Objects Alphabetically

arrayCarObjects.sort((a, b) => (a.brand > b.brand) ? 1 : -1);
theMaxx
la source
2

Version de la solution Cheeso avec tri inversé, j'ai également supprimé les expressions ternaires par manque de clarté (mais c'est un goût personnel).

function(prop, reverse) {
  return function(a, b) {
    if (typeof a[prop] === 'number') {
      return (a[prop] - b[prop]);
    }

    if (a[prop] < b[prop]) {
      return reverse ? 1 : -1;
    }

    if (a[prop] > b[prop]) {
      return reverse ? -1 : 1;
    }

    return 0;
  };
};
Marcs
la source
1
Pour être complètement inversé, les nombres ont besoinreturn !!reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Mark Schultheiss
Oui, comme maintenant pas de contre-vérification des numéros, merci, je devrais corriger cela. Mais pourquoi le double !c'est bien aussi:return reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Marcs
1
La !!contrainte de type force à une valeur de type booléen natif par opposition à la nature «falsifiée» de la valeur JavaScript, ce n'est pas strictement nécessaire mais clarifie le but au moins pour moi. Notez que lorsque vous renvoyez une valeur avec !!elle est un type booléen natif par opposition à un type natif avec une valeur "falsy", c'est-à-dire le typeof !!undefinedou typeof !!nulletc. retournez "boolean" Notez que !!" "c'est truemais !!""est false(espace, pas d'espace string) mais vous le saviez probablement déjà.
Mark Schultheiss