Ordinamento degli oggetti in base ai valori delle proprietà


88

Come implementare il seguente scenario utilizzando solo Javascript:

  • Crea un oggetto auto con proprietà (velocità massima, marca, ecc.)
  • Ordina un elenco di auto ordinate in base a tali proprietà

3
@durilai: JavaScript è orientato agli oggetti, il modello OO di JavaScript si basa sulla prototipazione ed è davvero molto versatile ... en.wikipedia.org/wiki/Prototype-based_programming
Christian C. Salvadó

Consiglio di usare lodash.js: lodash.com/docs#sortBy
Chemical Programmer

Risposte:


162

javascript ha la funzione di ordinamento che può prendere un'altra funzione come parametro - quella seconda funzione viene utilizzata per confrontare due elementi.

Esempio:

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, dal tuo commento vedo che stai usando la parola "sort" in un senso sbagliato. Nella programmazione "ordinare" significa "mettere le cose in un certo ordine", non "organizzare le cose in gruppi". Quest'ultimo è molto più semplice: è così che "ordinate" le cose nel mondo reale

  • crea due array vuoti ("scatole")
  • per ogni oggetto nella tua lista, controlla se corrisponde ai criteri
  • se sì, mettilo nella prima "scatola"
  • se no, mettilo nella seconda "scatola"

11
Nota semplice per praticità: this ( a.someProp - b.someProp) ordina dal più basso al più alto e viceversa ( b.someProp - a.someProp) ordina dal più alto al più basso. Fondamentalmente, se la funzione restituisce meno di 0, a viene prima di b.
user56reinstatemonica8

Tieni inoltre presente che questa soluzione funziona solo quando le proprietà in base a cui stai ordinando sono numeri. Questo funziona nell'esempio per l'ordinamento in base alla velocità massima, ma se desideri ordinare per marca di auto, questa soluzione non ordinerà le stringhe in ordine alfabetico. Cheeso fornisce una risposta per l'ordinamento sia per numeri che per stringhe.
Cole Marshall

23

Esempio.

Funziona su cscript.exe, su 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");

Puoi anche creare uno smistatore generale.

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

13

Ho scritto questa semplice funzione per me stesso:

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

ad esempio hai un elenco di auto:

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

6

Supponiamo di dover ordinare un elenco di oggetti in ordine crescente in base a una particolare proprietà, in questo esempio diciamo di dover ordinare in base alla proprietà "name", quindi di seguito è riportato il codice richiesto:

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"}]

1
Penso che tu abbia un errore di battitura? restituisce un ["nome"]. localeCompare (b. ["nome"]); dovrebbe essere restituito a ["nome"]. localeCompare (b ["nome"]); (rimuovere il. dopo b)
Little Brain

3

Con le funzioni freccia ES6 sarà così:

//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() può accettare una funzione di confronto (qui ho usato la notazione a freccia, ma le funzioni ordinarie funzionano allo stesso modo):

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'approccio di cui sopra copia il contenuto dell'array di automobili in uno nuovo e lo ordina alfabeticamente in base ai nomi dei marchi. Allo stesso modo, puoi passare una funzione diversa:

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

Se non ti dispiace cambiare l'array originale cars.sort(comparatorFunction)farà il trucco.


3

Ecco un breve esempio, che crea una serie di oggetti e ordina numericamente o alfabeticamente:

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

2

Una versione della soluzione Cheeso con inversione di ordinamento, ho anche rimosso le espressioni ternarie per mancanza di chiarezza (ma questo è gusto personale).

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

1
Per essere completamente invertiti i numeri hanno bisognoreturn !!reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Mark Schultheiss

Sì, perché ora nessun controllo inverso sui numeri, grazie, dovrei aggiustarlo. Ma perché il doppio !va bene anche questo:return reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Marcs

1
Il !!tipo forza la coercizione a un valore di tipo booleano nativo in contrasto con la natura "falsa" del valore JavaScript, non strettamente necessario ma chiarisce lo scopo almeno per me. Nota che quando restituisci un valore con !!esso è un tipo booleano nativo in contrasto con un tipo nativo con un valore "falso", vale a dire typeof !!undefinedo typeof !!nullecc. Return "booleano" Nota che !!" "è truema !!""è false(spazio, nessuno spazio nel stringa) ma probabilmente lo sapevi già.
Mark Schultheiss
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.