2012-07-07 62 views
9

Tôi tìm thấy một phương pháp tuyệt vời để sắp xếp một mảng của các đối tượng dựa trên một trong những tài sản như quy định tại:Làm thế nào để sắp xếp một mảng của các đối tượng với nhiều giá trị trường trong JavaScript

Sort array of objects by string property value in JavaScript

Sử dụng mà chức năng công trình hoàn toàn cho một loại duy nhất (trên tất cả các trình duyệt) và thậm chí là sắp xếp trong một loại EXCEPT khác bằng cách sử dụng Google Chrome! Đây là thói quen ảnh hưởng lớn Ege Özcan cho mảng của các đối tượng

function dynamicSort(property) { 
    return function (a,b) { 
     return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0; 
    } 
} 

Sử dụng một mảng có tên là "dữ liệu" (tất nhiên, mảng của tôi có rất nhiều cặp đối tượng trở lên) ...

var Data = [{Category: "Business", Value: "ABC"},{Category:"Personal", Value:"XYZ"}]; 

tôi có thể nhận một loại thích hợp nơi trật tự được liệt kê như tất cả các giá trị trong mỗi loại bằng cách làm này ...

Data.sort(dynamicSort("Value")); 
Data.sort(dynamicSort("Category")); 

bằng cách đầu tiên sắp xếp trên Value, và sau đó bởi Category, mảng của tôi đặt tất cả các giá trị theo thứ tự được sắp xếp với tất cả các giá trị Cơ sở kinh doanh được liệt kê trước và sau đó là tất cả các giá trị dựa trên Cá nhân. Hoàn hảo! Ngoại trừ trong Chrome nơi dữ liệu được sắp xếp đúng theo danh mục, nhưng thứ tự của các giá trị trong mỗi danh mục có vẻ khá ngẫu nhiên.

Có ai biết cách tốt hơn để thực hiện sắp xếp trong một sắp xếp cũng sẽ hoạt động trong Chrome không?

+2

sắp xếp theo A và sau đó phân loại độc lập bằng B _ không giống như sắp xếp theo A ** và ** B_. Nếu nó hoạt động trên một số trình duyệt thì đó là một tiếng sáo. – Alnitak

Trả lời

35

Tôi tạo ra một phiên bản đa thông số đó chức năng dynamicSort:

function dynamicSort(property) { 
    return function (obj1,obj2) { 
     return obj1[property] > obj2[property] ? 1 
      : obj1[property] < obj2[property] ? -1 : 0; 
    } 
} 

function dynamicSortMultiple() { 
    /* 
    * save the arguments object as it will be overwritten 
    * note that arguments object is an array-like object 
    * consisting of the names of the properties to sort by 
    */ 
    var props = arguments; 
    return function (obj1, obj2) { 
     var i = 0, result = 0, numberOfProperties = props.length; 
     /* try getting a different result from 0 (equal) 
     * as long as we have extra properties to compare 
     */ 
     while(result === 0 && i < numberOfProperties) { 
      result = dynamicSort(props[i])(obj1, obj2); 
      i++; 
     } 
     return result; 
    } 
} 

Tôi tạo ra một mảng như sau:

var arr = [ 
    {a:"a",b:"a",c:"a"}, 
    {a:"b",b:"a",c:"b"}, 
    {a:"b",b:"a",c:"a"}, 
    {a:"b",b:"a",c:"b"}, 
    {a:"b",b:"b",c:"a"}, 
    {a:"b",b:"b",c:"b"}, 
    {a:"b",b:"b",c:"a"}, 
    {a:"b",b:"b",c:"b"}, 
    {a:"b",b:"b",c:"a"}, 
    {a:"b",b:"b",c:"b"}, 
    {a:"b",b:"b",c:"a"}, 
    {a:"c",b:"b",c:"b"}, 
    {a:"c",b:"c",c:"a"} 
]; 

và nó làm việc khi tôi đã làm,

arr.sort(dynamicSortMultiple("c","b","a")); 

Và đây là một ví dụ làm việc: http://jsfiddle.net/ZXedp/

+1

cái này, cũng có nhiều thuộc tính: http://stackoverflow.com/questions/1129216/sorting-objects-in-an-array-by-a-field-value-in-javascript/4760279#4760279 –

1

Bạn cũng có thể muốn có một cái nhìn tại thenBy.js: https://github.com/Teun/thenBy.js

Nó cho phép bạn sử dụng Array.sort tiêu chuẩn, nhưng với firstBy() ThenBy() ThenBy() phong cách...

+0

Tốt hơn: 'firstBy = (function() {hàm tb (y) {var x = this; hàm f (a, b) {return x (a, b) || y (a, b);} f.thenBy = tb; return f;} return function (f) {f.thenBy = tb; return f;};})(); ' – Bergi

+0

Tôi quan tâm đến lý do tại sao điều này là tốt hơn. Bạn có thể chi tiết? Có thể sử dụng yêu cầu kéo? –

+0

1) chỉ một, chia sẻ 'sau đóBy' chức năng 2) không có không cần thiết' secondaryFunction' 3) nó ngắn hơn 4) nó chức năng hơn, bạn sẽ có vấn đề với 'var a = firstBy (x), b = a.thenBy (y), c = a.thenBy (z) 'vì' a' == 'b' ==' c' – Bergi

0

Đây là giải pháp của tôi. Nó nhanh hơn lodash của _.sortBy() loại chức năng nhiều cột trong khoảng hai lần (xem http://jsperf.com/multi-column-sort. tôi tạo ra nội dung của chức năng phân loại, sau đó sử dụng nó trong tiêu chuẩn .sort(). Nó hoạt động trong Chrome và Firefox là tốt.

function multiColumnSort(arr,sf) { 
    var s = ''; 
    sf.forEach(function(f,idx) { 
     s += 'if(arguments[0].'+f+'>arguments[1].'+f+')return 1;'; 
     s += 'else if(arguments[0].'+f+'==arguments[1].'+f+')'; 
     s += (idx < sf.length-1)? '{' : 'return 0'; 
    }); 
    s += Array(sf.length).join('}')+';return -1'; 
    return arr.sort(new Function(s)); 
}; 
5

cách đơn giản nhất để thực hiện một Javascript Multi-tiêu chuẩn Sắp xếp (hoặc Multi-Parameter Sắp xếp), là sử dụng .sort, nối các thông số nhiều với nhau, và so sánh hai đốt.

Ví dụ:

data.sort(function (a, b) { 

    var aConcat = a["property1"] + a["property2"]; 
    var bConcat = b["property1"] + b["property2"]; 

    if (aConcat > bConcat) { 
    return 1; 
    } else if (aConcat < bConcat) { 
    return -1; 
    } else { 
    return 0; 
    } 

}); 

tôi đã bao gồm một JsFiddle Script ở đây: http://jsfiddle.net/oahxg4u3/6/

1

bây giờ tôi bài này là khá cũ, dù sao tôi thấy nó ngày hôm nay và trích dẫn Ege Özcan, tôi được cải thiện giải pháp tuyệt vời của mình triển khai chức năng giống như SQL DES-ASC cho bất kỳ ai quan tâm (http://jsfiddle.net/ZXedp/65/):

function dynamicSortMultiple() { 
    var props=[]; 
    /*Let's separate property name from ascendant or descendant keyword*/ 
    for(var i=0; i < arguments.length; i++){ 
     var splittedArg=arguments[i].split(/ +/); 
     props[props.length]=[splittedArg[0], (splittedArg[1] ? splittedArg[1].toUpperCase() : "ASC")]; 
    } 
    return function (obj1, obj2) { 
     var i = 0, result = 0, numberOfProperties = props.length ; 
     /*Cycle on values until find a difference!*/ 
     while(result === 0 && i < numberOfProperties) { 
      result = dynamicSort(props[i][0], props[i][1])(obj1, obj2); 
      i++; 
     } 
     return result; 
    } 
} 

/*Base function returning -1,1,0 for custom sorting*/ 
function dynamicSort(property, isAscDesc) { 
    return function (obj1,obj2) { 
     if(isAscDesc==="DESC"){ 
      return ((obj1[property] > obj2[property]) ? (-1) : ((obj1[property] < obj2[property]) ? (1) : (0))); 
     } 
     /*else, if isAscDesc==="ASC"*/ 
     return ((obj1[property] > obj2[property]) ? (1) : ((obj1[property] < obj2[property]) ? (-1) : (0))); 
    } 
} 

gọi hàm bằng một cái gì đó như thế này:

arr.sort(dynamicSortMultiple("c DESC","b Asc","a")); 
Các vấn đề liên quan