Sắp xếp các đối tượng theo giá trị thuộc tính


88

Cách triển khai tình huống sau chỉ sử dụng Javascript:

  • Tạo một đối tượng ô tô với các thuộc tính (tốc độ tối đa, thương hiệu, v.v.)
  • Sắp xếp danh sách xe ô tô theo thứ tự của các thuộc tính đó

3
@durilai: JavaScript đối tượng theo định hướng, mô hình OO của JavaScript được dựa trên Prototyping và thực sự, thực sự linh hoạt ... en.wikipedia.org/wiki/Prototype-based_programming
Christian C. Salvadó

Tôi khuyên bạn nên sử dụng lodash.js: lodash.com/docs#sortBy
Hóa chất Programmer

Câu trả lời:


159

javascript có hàm sắp xếp có thể nhận một hàm khác làm tham số - hàm thứ hai đó được sử dụng để so sánh hai phần tử.

Thí dụ:

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 

được rồi, từ nhận xét của bạn, tôi thấy rằng bạn đang sử dụng từ 'sắp xếp' theo nghĩa sai. Trong lập trình "sort" có nghĩa là "sắp xếp mọi thứ theo một thứ tự nhất định", không phải "sắp xếp mọi thứ theo nhóm". Cách sau đơn giản hơn nhiều - đây chỉ là cách bạn "sắp xếp" mọi thứ trong thế giới thực

  • tạo hai mảng trống ("hộp")
  • cho mỗi đối tượng trong danh sách của bạn, hãy kiểm tra xem nó có phù hợp với tiêu chí không
  • nếu có, hãy đặt nó vào "hộp" đầu tiên
  • nếu không, hãy đặt nó vào "hộp" thứ hai

10
Lưu ý đơn giản để thuận tiện: this ( a.someProp - b.someProp) sắp xếp từ thấp nhất đến cao nhất và ngược lại ( b.someProp - a.someProp) sắp xếp từ cao nhất đến thấp nhất. Về cơ bản, nếu hàm trả về nhỏ hơn 0, a đứng trước b.
user56reinstatemonica8

Cũng lưu ý rằng giải pháp này chỉ hoạt động khi các thuộc tính bạn đang sắp xếp là số. Điều này hoạt động trong ví dụ sắp xếp theo tốc độ tối đa, nhưng nếu bạn muốn sắp xếp theo thương hiệu xe hơi, giải pháp này sẽ không sắp xếp các chuỗi theo thứ tự bảng chữ cái. Cheeso cung cấp câu trả lời cho việc sắp xếp theo cả số và chuỗi.
Cole Marshall

23

Thí dụ.

Điều này chạy trên cscript.exe, trên 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");

Bạn cũng có thể tạo một bộ phân loại chung.

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

Tôi đã viết hàm đơn giản này cho chính mình:

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

ví dụ bạn có danh sách các xe:

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

6

Giả sử chúng ta phải sắp xếp danh sách các đối tượng theo thứ tự tăng dần dựa trên một thuộc tính cụ thể, trong ví dụ này giả sử chúng ta phải sắp xếp dựa trên thuộc tính "name", sau đó dưới đây là mã bắt buộc:

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
Tôi nghĩ rằng bạn có một lỗi đánh máy? return a ["name"]. localeCompare (b. ["name"]); nên trả về a ["name"]. localeCompare (b ["name"]); (loại bỏ sau b.)
Ít Brain

3

Với các hàm mũi tên của ES6, nó sẽ như thế này:

//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() có thể chấp nhận một hàm so sánh (ở đây tôi đã sử dụng ký hiệu mũi tên, nhưng các hàm thông thường hoạt động giống nhau):

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

Cách tiếp cận trên sao chép nội dung của mảng ô tô vào một mảng mới và sắp xếp theo thứ tự bảng chữ cái dựa trên tên thương hiệu. Tương tự, bạn có thể chuyển một hàm khác:

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

Nếu bạn không nhớ việc thay đổi mảng ban đầu cars.sort(comparatorFunction)sẽ thực hiện được mẹo.


3

Dưới đây là một ví dụ ngắn gọn, tạo và mảng các đối tượng và sắp xếp theo số hoặc theo bảng chữ cái:

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

Một phiên bản của giải pháp Cheeso với phân loại ngược, tôi cũng đã loại bỏ các biểu thức bậc ba vì thiếu rõ ràng (nhưng đây là sở thích cá nhân).

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
Để được hoàn toàn đảo ngược những con số cầnreturn !!reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Đánh dấu Schultheiss

Có, vì bây giờ không có kiểm tra ngược lại trên số, cảm ơn bạn, tôi nên sửa điều đó. Nhưng tại sao gấp đôi !điều này cũng tốt:return reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
Marcs

1
Các !!lực lượng kiểu ép buộc một giá trị kiểu boolean bản địa như trái ngược với "falsy" bản chất của giá trị JavaScript, không cần đúng nhưng làm rõ mục đích ít nhất đối với tôi. Lưu ý rằng khi bạn trả lại một giá trị với !!nó là một loại Boolean có nguồn gốc như trái ngược với một loại bản địa với một giá trị "falsy" mà là để nói rằng typeof !!undefinedhay typeof !!null, vv trở lại "boolean" Lưu ý rằng !!" "truenhưng !!""false(không gian, không gian trong string) nhưng bạn có thể đã biết điều đó.
Mark Schultheiss
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.