Classificando objetos por valores de propriedade


88

Como implementar o seguinte cenário usando apenas Javascript:

  • Crie um objeto de carro com propriedades (velocidade máxima, marca, etc.)
  • Classifique uma lista de carros ordenados por essas propriedades

3
@durilai: JavaScript é orientado a objetos, o modelo OO de JavaScript é baseado em prototipagem e é muito, muito versátil ... en.wikipedia.org/wiki/Prototype-based_programming
Christian C. Salvadó

Eu recomendo usar lodash.js: lodash.com/docs#sortBy
Chemical Programmer

Respostas:


159

javascript tem a função de classificação que pode ter outra função como parâmetro - essa segunda função é usada para comparar dois elementos.

Exemplo:

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, pelo seu comentário, vejo que você está usando a palavra 'classificar' no sentido errado. Na programação, "classificar" significa "colocar as coisas em uma certa ordem", não "organizar as coisas em grupos". O último é muito mais simples - é assim que você "classifica" as coisas no mundo real

  • faça duas matrizes vazias ("caixas")
  • para cada objeto em sua lista, verifique se ele atende aos critérios
  • se sim, coloque-o na primeira "caixa"
  • se não, coloque-o na segunda "caixa"

10
Nota simples para conveniência: this ( a.someProp - b.someProp) classifica do mais baixo para o mais alto , e reverse ( b.someProp - a.someProp) classifica do mais alto para o mais baixo. Basicamente, se a função retornar menos que 0, a vem antes de b.
user56reinstatemonica8

Observe também que essa solução só funciona quando as propriedades que você está classificando são números. Isso funciona no exemplo para classificar por velocidade máxima, mas se você quiser classificar por marca de carro, essa solução não classificará as strings em ordem alfabética. Cheeso fornece uma resposta para classificação por números e strings.
Cole Marshall

23

Exemplo.

Isso é executado em cscript.exe, no 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");

Você também pode fazer uma classificação geral.

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

Eu escrevi esta função simples para mim:

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 exemplo, você tem uma lista de carros:

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

6

Digamos que temos que classificar uma lista de objetos em ordem crescente com base em uma propriedade particular, neste exemplo, digamos que temos que classificar com base na propriedade "nome", abaixo está o código necessário:

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
Eu acho que você tem um erro de digitação? retornar um ["nome"]. localeCompare (b. ["nome"]); deve retornar a ["nome"]. localeCompare (b ["nome"]); (remova o. após b)
Little Brain

3

Com as funções de seta ES6 , será assim:

//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() pode aceitar uma função de comparador (aqui eu usei a notação de seta, mas as funções comuns funcionam da mesma forma):

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

A abordagem acima copia o conteúdo da matriz de carros em uma nova e classifica em ordem alfabética com base nos nomes das marcas. Da mesma forma, você pode passar uma função 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 } ]

Se você não se importar em mudar a matriz original cars.sort(comparatorFunction), isso resolverá o problema.


3

Aqui está um pequeno exemplo, que cria uma matriz de objetos e classifica numericamente ou 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

Uma versão da solução Cheeso com classificação reversa, também removi as expressões ternárias por falta de clareza (mas este é o gosto pessoal).

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
Para ser totalmente revertido, os números precisamreturn !!reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Mark Schultheiss

Sim, como agora não há verificação reversa nos números, obrigado, devo consertar isso. Mas por que o dobro !também está bom:return reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Marcs

1
As !!forças de coerção de tipo para um valor de tipo booleano nativo em oposição à natureza "falsa" do valor JavaScript, não estritamente necessário, mas esclarece o propósito pelo menos para mim. Observe que, quando você retorna um valor com !!ele, é um tipo booleano nativo em oposição a um tipo nativo com um valor "falso", que quer dizer o typeof !!undefinedou typeof !!nulletc. retorna "booleano" Observe que !!" "é truemas !!""é false(espaço, nenhum espaço no string), mas você provavelmente já sabia disso.
Mark Schultheiss
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.