Ordenar objetos por valores de propiedad

88

Cómo implementar el siguiente escenario usando solo Javascript:

  • Crea un objeto de coche con propiedades (velocidad máxima, marca, etc.)
  • Ordenar una lista de autos ordenados por esas propiedades
Constructor
fuente
3
@durilai: JavaScript está orientado a objetos, el modelo OO de JavaScript se basa en la creación de prototipos y es realmente muy versátil ... en.wikipedia.org/wiki/Prototype-based_programming
Christian C. Salvadó
Recomiendo usar lodash.js: lodash.com/docs#sortBy
Programador químico

Respuestas:

159

javascript tiene la función de clasificación que puede tomar otra función como parámetro; esa segunda función se usa para comparar dos elementos.

Ejemplo:

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, por tu comentario veo que estás usando la palabra 'ordenar' en un sentido equivocado. En programación, "ordenar" significa "poner las cosas en un cierto orden", no "organizar las cosas en grupos". Esto último es mucho más simple: así es como se "clasifican" las cosas en el mundo real.

  • hacer dos matrices vacías ("cajas")
  • para cada objeto en su lista, verifique si coincide con los criterios
  • si es así, colóquelo en la primera "casilla"
  • si no, ponlo en la segunda "caja"
usuario187291
fuente
10
Nota simple por conveniencia: este ( a.someProp - b.someProp) ordena de menor a mayor , y el inverso ( b.someProp - a.someProp) ordena de mayor a menor. Básicamente, si la función devuelve menos de 0, a viene antes de b.
user56reinstatemonica8
También tenga en cuenta que esta solución solo funciona cuando las propiedades por las que está ordenando son números. Esto funciona en el ejemplo para ordenar por velocidad máxima, pero si desea ordenar por marca de automóvil, esta solución no ordenará las cadenas alfabéticamente. Cheeso proporciona una respuesta para ordenar tanto por números como por cadenas.
Cole Marshall
23

Ejemplo.

Esto se ejecuta en cscript.exe, en 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");

También puedes hacer un clasificador general.

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
fuente
13

He escrito esta función simple para mí:

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

por ejemplo, tienes una lista de coches:

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

Digamos que tenemos que ordenar una lista de objetos en orden ascendente en función de una propiedad en particular, en este ejemplo, digamos que tenemos que ordenar en función de la propiedad "nombre", luego a continuación se muestra el código requerido:

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
fuente
1
Creo que tienes un error tipográfico. devuelve un ["nombre"]. localeCompare (b. ["nombre"]); debe devolver un ["nombre"]. localeCompare (b ["nombre"]); (quitar el. después de b)
Little Brain
3

Con las funciones de flecha de ES6 será así:

//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() puede aceptar una función de comparación (aquí usé notación de flecha, pero las funciones ordinarias funcionan igual):

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

El enfoque anterior copia el contenido de la matriz de coches en uno nuevo y lo ordena alfabéticamente según los nombres de las marcas. Del mismo modo, puede pasar una función diferente:

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 no le importa mutar la matriz original, cars.sort(comparatorFunction)será suficiente.

Vértigo Farzad
fuente
3

Aquí hay un breve ejemplo, que crea una matriz de objetos y los ordena numérica o alfabéticamente:

// 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
fuente
2

Una versión de la solución Cheeso con clasificación inversa, también eliminé las expresiones ternarias por falta de claridad (pero esto es un gusto personal).

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;
  };
};
Marcos
fuente
1
Para invertir por completo los números se necesitanreturn !!reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Mark Schultheiss
Sí, como ahora no hay verificación inversa en los números, gracias, debería arreglar eso. Pero por qué el doble !esto también está bien:return reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
2017
1
Las !!fuerzas de tipo coerción a un valor de tipo booleano nativo en oposición a la naturaleza "falsa" del valor de JavaScript, no es estrictamente necesario pero aclara el propósito al menos para mí. Tenga en cuenta que cuando devuelve un valor con !!él, es un tipo booleano nativo en lugar de un tipo nativo con un valor "falso", es decir, typeof !!undefinedo, typeof !!nulletc., devuelve "booleano". Tenga en cuenta que !!" "es truepero !!""es false(espacio, sin espacio en el string) pero probablemente ya lo sabías.
Mark Schultheiss