Sortowanie obiektów według wartości właściwości

88

Jak zaimplementować następujący scenariusz tylko przy użyciu JavaScript:

  • Utwórz obiekt samochodu z właściwościami (maksymalna prędkość, marka itp.)
  • Sortuj listę samochodów uporządkowaną według tych właściwości
Konstruktor
źródło
3
@durilai: JavaScript jest zorientowany obiektowo, model OO JavaScript oparty jest na prototypowaniu i jest naprawdę, bardzo wszechstronny ... pl.wikipedia.org/wiki/Prototype-based_programming
Christian C. Salvadó
Polecam korzystanie z lodash.js: lodash.com/docs#sortBy
programista chemiczny

Odpowiedzi:

159

javascript ma funkcję sortowania, która może przyjąć inną funkcję jako parametr - ta druga funkcja jest używana do porównania dwóch elementów.

Przykład:

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, z twojego komentarza wynika, że ​​używasz słowa „sort” w złym znaczeniu. W programowaniu „sortowanie” oznacza „układanie rzeczy w określonej kolejności”, a nie „układanie rzeczy w grupy”. To drugie jest znacznie prostsze - tak właśnie „sortujesz” rzeczy w prawdziwym świecie

  • utwórz dwie puste tablice („pudełka”)
  • dla każdego obiektu na liście sprawdź, czy spełnia kryteria
  • jeśli tak, umieść go w pierwszym „pudełku”
  • jeśli nie, umieść go w drugim „pudełku”
user187291
źródło
10
Prosta uwaga dla wygody: to ( a.someProp - b.someProp) sortuje od najniższego do najwyższego , a odwrotne ( b.someProp - a.someProp) sortuje od najwyższego do najniższego. Zasadniczo, jeśli funkcja zwraca mniej niż 0, a występuje przed b.
user56reinstatemonica8
Pamiętaj również, że to rozwiązanie działa tylko wtedy, gdy właściwości, według których sortujesz, są liczbami. Działa to w przykładzie sortowania według maksymalnej prędkości, ale jeśli chcesz sortować według marki samochodu, to rozwiązanie nie będzie sortować ciągów alfabetycznie. Cheeso zapewnia odpowiedź na sortowanie według liczb i ciągów znaków.
Cole Marshall
23

Przykład.

Działa na cscript.exe w systemie 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");

Możesz także wykonać ogólny sortownik.

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");
Ser
źródło
13

Napisałem dla siebie tę prostą funkcję:

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

na przykład masz listę samochodów:

var cars= [{brand: 'audi', speed: 240}, {brand: 'fiat', speed: 190}];
var carsSortedByBrand = sortObj(cars, 'brand');
var carsSortedBySpeed = sortObj(cars, 'speed');
slavugan
źródło
6

Powiedzmy, że musimy posortować listę obiektów w porządku rosnącym na podstawie określonej właściwości, w tym przykładzie powiedzmy, że musimy posortować według właściwości „name”, a poniżej jest wymagany kod:

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
źródło
1
Myślę, że masz literówkę? zwraca ["nazwa"]. localeCompare (b. ["nazwa"]); powinno zostać zwrócone a ["nazwa"]. localeCompare (b ["nazwa"]); (usuń. po b)
Little Brain
3

Z funkcjami strzałkowymi ES6 będzie tak:

//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() może przyjąć funkcję komparatora (tutaj użyłem notacji strzałkowej, ale zwykłe funkcje działają tak samo):

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

Powyższe podejście kopiuje zawartość tablicy samochodów do nowej i sortuje ją alfabetycznie na podstawie nazw marek. Podobnie możesz przekazać inną funkcję:

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

Jeśli nie masz nic przeciwko mutacji oryginalnej tablicy, cars.sort(comparatorFunction)wystarczy.

Farzad Vertigo
źródło
3

Oto krótki przykład, który tworzy tablicę obiektów i sortuje numerycznie lub alfabetycznie:

// 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
źródło
2

Wersja rozwiązania Cheeso z odwrotnym sortowaniem, usunąłem również trójskładnikowe wyrażenia dla niejasności (ale to jest osobisty gust).

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
źródło
1
Aby być w pełni odwróconym, liczby potrzebująreturn !!reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Mark Schultheiss
Tak, ponieważ teraz nie ma odwrotnego sprawdzania numerów, dziękuję, powinienem to naprawić. Ale dlaczego podwójnie !to też jest w porządku:return reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Marcs
1
!!Rodzaj sił przymusu z natywną wartość logiczna typu, w przeciwieństwie do „natury” falsy wartości JavaScript, ale nie jest to bezwzględnie konieczne wyjaśnia zastosowania przynajmniej dla mnie. Należy pamiętać, że po powrocie z wartości !!jest to rodzimy typ Boolean w przeciwieństwie do natywnego typu z „falsy” wartości, która ma powiedzieć typeof !!undefinedlub typeof !!nullitp zwrotny „logiczną” Należy pamiętać, że !!" "jest true, ale !!""jest false(przestrzeń, nie ma miejsca w string), ale prawdopodobnie już to wiedziałeś.
Mark Schultheiss