Сортування об’єктів за значеннями властивостей


88

Як реалізувати такий сценарій, використовуючи лише Javascript:

  • Створіть автомобільний об’єкт із властивостями (максимальна швидкість, марка тощо)
  • Відсортуйте список автомобілів, упорядкованих за цими властивостями

3
@durilai: JavaScript є об'єктно-орієнтованим, OO-модель JavaScript заснована на прототипуванні і дійсно, дійсно універсальна ... en.wikipedia.org/wiki/Prototype-based_programming
Крістіан Сальвадо,

Я рекомендую використовувати lodash.js: lodash.com/docs#sortBy
Програміст хімічних технологій

Відповіді:


159

javascript має функцію сортування, яка може приймати іншу функцію як параметр - ця друга функція використовується для порівняння двох елементів.

Приклад:

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 

добре, з вашого коментаря я бачу, що ви вживаєте слово "сортувати" в неправильному сенсі. У програмуванні "сортувати" означає "впорядковувати речі в певному порядку", а не "розкладати речі по групах". Останнє набагато простіше - саме так ви «сортуєте» речі в реальному світі

  • зробити два порожні масиви ("коробки")
  • для кожного об’єкта у вашому списку перевірте, чи відповідає він критеріям
  • якщо так, поставте це в першу "коробку"
  • якщо ні, помістіть у другу "коробку"

10
Проста примітка для зручності: це ( a.someProp - b.someProp) сортує від найнижчого до найвищого , а зворотне ( b.someProp - a.someProp) сортує від найвищого до найнижчого. В основному, якщо функція повертає менше 0, a стоїть перед b.
user56reinstatemonica8

Також зверніть увагу, що це рішення працює лише тоді, коли властивості, за якими ви сортуєте, є числами. Це працює в прикладі для сортування за максимальною швидкістю, але якщо ви хочете сортувати за маркою автомобіля, це рішення не буде сортувати рядки за алфавітом. Cheeso надає відповідь на сортування як за номерами, так і за рядками.
Коул Маршалл,

23

Приклад.

Це працює на cscript.exe у 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");

Ви також можете зробити загальний сортувальник.

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

Я написав для себе цю просту функцію:

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

наприклад у вас є список автомобілів:

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

6

Скажімо, ми маємо сортувати список об’єктів за зростанням на основі певної властивості, у цьому прикладі скажімо, що ми маємо сортувати на основі властивості „name”, тоді нижче наведено необхідний код:

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
Думаю, у вас є друкарська помилка? повертає ["name"]. localeCompare (b. ["name"]); повинно бути повернути [[ім'я "]. localeCompare (b [" ім’я "]); (прибрати. після b)
Маленький Мозок

3

З функціями стрілок ES6 це буде так:

//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() може прийняти функцію порівняння (тут я використовував позначення стрілки, але звичайні функції працюють однаково):

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

Вищевказаний підхід копіює вміст масиву автомобілів у новий та сортує його в алфавітному порядку на основі брендів. Аналогічно, ви можете передати іншу функцію:

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

Якщо ви не проти змінити оригінальний масив, cars.sort(comparatorFunction)це зробить трюк.


3

Ось короткий приклад, який створює і масив об’єктів, і сортує числово або за алфавітом:

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

Версію розчину Cheeso із зворотним сортуванням, я також видалив тернарні вирази через відсутність чіткості (але це особистий смак).

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
Щоб повністю змінити цифри, потрібноreturn !!reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Марк Шультхайс

Так, оскільки зараз немає зворотної перевірки чисел, дякую, я повинен це виправити. Але чому вдвічі !це теж добре:return reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Маркс

1
!!Тип сили примусу до нативної значення логічного типу , на відміну від «falsy» характер цінності JavaScript, строго кажучи , не потрібно , але прояснює призначення , по крайней мере для мене. Зверніть увагу, що коли ви повертаєте значення з !!ним, це власний логічний тип, на відміну від власного типу зі значенням "хибність", тобто " typeof !!undefinedабо typeof !!nullлогічне повернення" Примітка, що !!" "є, trueале !!""є false(пробіл, пробіл у рядок), але ви, мабуть, це вже знали.
Mark Schultheiss
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.