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
Construtor
fonte
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"
user187291
fonte
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");
Cheeso
fonte
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');
Slavugan
fonte
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"}]
Jayanth G
fonte
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.

Farzad Vertigo
fonte
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);
theMaxx
fonte
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;
  };
};
Marcs
fonte
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