2012-07-07 11 views
9

Znalazłem świetny sposób, aby posortować tablicę obiektów w oparciu o jedną z właściwości, jak zdefiniowano w:Jak sortować tablicę obiektów z wielu wartości pola w JavaScript

Sort array of objects by string property value in JavaScript

Korzystanie że dzieła funkcyjnych idealnie dla jednego sortowania (we wszystkich przeglądarkach), a nawet sortowania w ramach innego rodzaju, Z WYJĄTKIEM korzystania z Google Chrome! Oto wielka rutyna rodzaj Ege Ozcan dla tablic obiektów

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

pomocą tablicy o nazwie „Data” (oczywiście, moja tablica ma wiele więcej par Object) ...

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

mogę dostać właściwa kolejność sortowania, gdzie znajduje się na liście wszystkich wartości w każdej kategorii w ten sposób ...

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

przez pierwsze sortowanie Value, a następnie przez Category, moja tablica umieszcza wszystkie wartości w porządku posortowanym, najpierw wszystkie wartości baz danych biznesowych, a następnie wszystkie wartości oparte na danych osobistych. Idealny! Z wyjątkiem Chrome, w którym dane są sortowane według kategorii, ale kolejność wartości w każdej kategorii wydaje się raczej losowa.

Czy ktoś wie o lepszym sposobie sortowania w rodzaju, który również działa w Chrome?

+2

sortując A, a następnie niezależnie sortując B nie _is taka sama jak sortując A ** i ** B_. Jeśli zadziałało w niektórych przeglądarkach, był to błąd. – Alnitak

Odpowiedz

35

stworzyłem wersję multi-parametr tej funkcji 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; 
    } 
} 

stworzyłem tablicę następująco:

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

i to działało, kiedy ja,

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

A oto działający przykład: http://jsfiddle.net/ZXedp/

+1

ten ma również wiele właściwości: http://stackoverflow.com/questions/1129216/sorting-objects-in-an-array-by-a-field-value-in-javascript/4760279#4760279 –

1

Można też rzucić okiem na thenBy.js: https://github.com/Teun/thenBy.js

To pozwala na użycie standardowego Array.sort, ale z firstBy() thenBy() thenBy() styl...

+0

Lepiej: 'firstBy = (function() {function tb (y) {var x = this; funkcja f (a, b) {return x (a, b) || y (a, b);} f.thenBy = tb; return f;} funkcja return (f) {f.thenBy = tb; return f;};})(); ' – Bergi

+0

Jestem zainteresowany tym, dlaczego jest lepiej. Czy możesz szczegółowo? Może przy użyciu żądania ściągnięcia? –

+0

1) tylko jedna, wspólna funkcja 'thenBy' 2) brak niepotrzebnego' secondaryFunction' 3) jest krótszy 4) jest bardziej funkcjonalny, twoje miałoby problemy z 'var a = firstBy (x), b = a.thenBy (y), c = a.thenBy (z) 'ponieważ' a' == 'b' ==' c' – Bergi

0

Oto moje rozwiązanie. To szybciej niż lodash za _.sortBy sort() funkcja multi-kolumna około dwa razy (patrz http://jsperf.com/multi-column-sort. wygenerować tekst funkcję sortowania, a następnie używać go w standardowym .sort(). To działa w Chrome i Firefox jak również.

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

najłatwiej wykonać javascript wielokryterialnej Sort (lub wielu parametrów Sort), jest użycie .sort, złączyć ze sobą wiele parametrów i porównać dwa żądła.

Na przykład:

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

}); 

podaję Script JsFiddle tutaj: http://jsfiddle.net/oahxg4u3/6/

1

I teraz ten post jest dość stary, w każdym razie uważam, że to dzisiaj i cytowanie Ege Özcan, poprawiłem jego doskonałe rozwiązanie implementujące funkcjonalność SQL-Like DESC-ASC dla wszystkich zainteresowanych (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))); 
    } 
} 

wywołanie funkcji przez coś takiego:

arr.sort(dynamicSortMultiple("c DESC","b Asc","a")); 
Powiązane problemy