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

1331

Mam następujące obiekty korzystające z AJAX i zapisałem je w tablicy:

var homes = [
    {
        "h_id": "3",
        "city": "Dallas",
        "state": "TX",
        "zip": "75201",
        "price": "162500"
    }, {
        "h_id": "4",
        "city": "Bevery Hills",
        "state": "CA",
        "zip": "90210",
        "price": "319250"
    }, {
        "h_id": "5",
        "city": "New York",
        "state": "NY",
        "zip": "00010",
        "price": "962500"
    }
];

Jak utworzyć funkcję do sortowania obiektów według pricewłaściwości w porządku rosnącym lub malejącym przy użyciu tylko JavaScript?

TomHankers
źródło
najszybszym sposobem jest użycie izomorficznego modułu macierzy sortowania , który działa natywnie zarówno w przeglądarce, jak i w węźle, obsługując dowolny typ danych wejściowych, pól obliczeniowych i niestandardowe porządki sortowania.
Lloyd

Odpowiedzi:

1674

Sortuj domy według ceny w porządku rosnącym:

homes.sort(function(a, b) {
    return parseFloat(a.price) - parseFloat(b.price);
});

Lub po wersji ES6:

homes.sort((a, b) => parseFloat(a.price) - parseFloat(b.price));

Część dokumentacji można znaleźć tutaj .

Stobor
źródło
182
Możesz użyć string1.localeCompare(string2)do porównania ciągów
bradvido
62
Należy pamiętać, że localeCompare()jest sprawa niewrażliwe . Jeśli chcesz rozróżniać małe i wielkie litery, możesz użyć (string1 > string2) - (string1 < string2). Wartości logiczne są wymuszane na liczby całkowite 0 i 1 w celu obliczenia różnicy.
Don Kirkby
2
Dzięki za aktualizację, @Pointy, nie pamiętam, że napotkałem ten problem, ale być może zachowanie zmieniło się w ciągu ostatnich kilku lat. Niezależnie od tego localeCompare()dokumentacja pokazuje, że możesz jawnie stwierdzić, czy chcesz rozróżniać wielkość liter, sortowanie numeryczne i inne opcje.
Don Kirkby
2
@ sg28 Myślę, że źle zrozumiałeś wyjaśnienie MDN. Nie mówi, że funkcja sortowania nie jest niezawodna , mówi, że nie jest stabilna . Rozumiem, dlaczego może to być mylące, ale nie oznacza to, że nie nadaje się do użytku. W kontekście algorytmów sortowania termin stabilny ma określone znaczenie - że „równe” elementy na liście są sortowane w tej samej kolejności, co na wejściu . Jest to całkowicie niezwiązane z ideą kodu, który jest niestabilny (tj. Nie jest jeszcze gotowy do użycia).
Stobor
1
Jeśli chcesz sortować według określonych wartości ciągu, na przykład według miasta, możesz użyć: this.homes.sort ((bieżący, następny) => {return current.city.localeCompare (next.city)});
Jorge Valvert,
675

Oto bardziej elastyczna wersja, która pozwala tworzyć funkcje sortowania wielokrotnego użytku i sortować według dowolnego pola.

const sort_by = (field, reverse, primer) => {

  const key = primer ?
    function(x) {
      return primer(x[field])
    } :
    function(x) {
      return x[field]
    };

  reverse = !reverse ? 1 : -1;

  return function(a, b) {
    return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
  }
}


//Now you can sort by any field at will...

const homes=[{h_id:"3",city:"Dallas",state:"TX",zip:"75201",price:"162500"},{h_id:"4",city:"Bevery Hills",state:"CA",zip:"90210",price:"319250"},{h_id:"5",city:"New York",state:"NY",zip:"00010",price:"962500"}];

// Sort by price high to low
console.log(homes.sort(sort_by('price', true, parseInt)));

// Sort by city, case-insensitive, A-Z
console.log(homes.sort(sort_by('city', false, (a) =>  a.toUpperCase()
)));

Tryptyk
źródło
7
nickb - źle odczytujesz kod. sort_bydziała w O (1) i zwraca funkcję używaną przez wbudowane sortowanie (O (N log N)) do porównywania pozycji na liście. Całkowita złożoność wynosi O (n log n) * O (1), co zmniejsza się do O (n log n) lub jest takie samo jak szybkie sortowanie.
Tryptyk
1
Jednym z moich problemów jest to, że przy odwróceniu = fałsz posortuje liczby jako 1,2,3,4 ... ale ciągi jako z, y, x ...
Abby
4
Małe ulepszenie:var key = primer ? function (x) { return primer(x[field]); } : function (x) { return x[field]; }
ErikE
6
Choć [1,-1][+!!reverse]wygląda świetnie, jest to straszna rzecz. Jeśli użytkownik nie może poprawnie wywołać metody, ukaraj go, nie próbuj w jakiś sposób tego zrozumieć, bez względu na wszystko.
Ingo Bürk,
2
Czy nie byłoby lepiej przygotować dane źródłowe, spowodowałoby to kolejne parsowanie, gdy wyraźnie dane źródłowe wymagają pewnych poprawek.
Gerrit Brink
134

Aby go posortować, musisz utworzyć funkcję komparatora, przyjmującą dwa argumenty. Następnie wywołaj funkcję sortowania z tą funkcją komparatora w następujący sposób:

// a and b are object elements of your array
function mycomparator(a,b) {
  return parseInt(a.price, 10) - parseInt(b.price, 10);
}
homes.sort(mycomparator);

Jeśli chcesz sortować rosnąco, przełącz wyrażenia po obu stronach znaku minus.

Ricardo Marimon
źródło
3
A oto odniesienie, które faktycznie wyjaśnia ten temat zamiast powiedzieć „jest zbyt skomplikowane, i tak go nie zrozumiesz”: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Roland Illig
51

do sortowania napisów na wypadek, gdyby ktoś tego potrzebował,

const dataArr = {

  "hello": [{
    "id": 114,
    "keyword": "zzzzzz",
    "region": "Sri Lanka",
    "supportGroup": "administrators",
    "category": "Category2"
  }, {
    "id": 115,
    "keyword": "aaaaa",
    "region": "Japan",
    "supportGroup": "developers",
    "category": "Category2"
  }]

};
const sortArray = dataArr['hello'];

console.log(sortArray.sort((a, b) => {
  if (a.region < b.region)
    return -1;
  if (a.region > b.region)
    return 1;
  return 0;
}));

Ishan Liyanage
źródło
38

Jeśli masz przeglądarkę zgodną z ES6 , możesz użyć:

Różnica między rosnącym a malejącym porządkiem sortowania jest znakiem wartości zwracanej przez funkcję porównywania:

var ascending = homes.sort((a, b) => Number(a.price) - Number(b.price));
var descending = homes.sort((a, b) => Number(b.price) - Number(a.price));

Oto działający fragment kodu:

var homes = [{
  "h_id": "3",
  "city": "Dallas",
  "state": "TX",
  "zip": "75201",
  "price": "162500"
}, {
  "h_id": "4",
  "city": "Bevery Hills",
  "state": "CA",
  "zip": "90210",
  "price": "319250"
}, {
  "h_id": "5",
  "city": "New York",
  "state": "NY",
  "zip": "00010",
  "price": "962500"
}];

homes.sort((a, b) => Number(a.price) - Number(b.price));
console.log("ascending", homes);

homes.sort((a, b) => Number(b.price) - Number(a.price));
console.log("descending", homes);

Stephen Quan
źródło
22

Chcesz posortować w JavaScript, prawda? To, czego chcesz, to sort()funkcja . W takim przypadku musisz napisać funkcję porównawczą i przekazać ją sort(), więc coś takiego:

function comparator(a, b) {
    return parseInt(a["price"], 10) - parseInt(b["price"], 10);
}

var json = { "homes": [ /* your previous data */ ] };
console.log(json["homes"].sort(comparator));

Twój komparator pobiera jeden z zagnieżdżonych skrótów wewnątrz tablicy i decyduje, który z nich jest wyższy, zaznaczając pole „cena”.

Tim Gilbert
źródło
21

Polecam GitHub: Array sortBy - najlepsza implementacja sortBymetody wykorzystującej transformację Schwartziana

Ale na razie wypróbujemy to podejście Gist: sortBy-old.js .
Stwórzmy metodę sortowania tablic, które mogą układać obiekty według niektórych właściwości.

Tworzenie funkcji sortowania

var sortBy = (function () {
  var toString = Object.prototype.toString,
      // default parser function
      parse = function (x) { return x; },
      // gets the item to be sorted
      getItem = function (x) {
        var isObject = x != null && typeof x === "object";
        var isProp = isObject && this.prop in x;
        return this.parser(isProp ? x[this.prop] : x);
      };

  /**
   * Sorts an array of elements.
   *
   * @param  {Array} array: the collection to sort
   * @param  {Object} cfg: the configuration options
   * @property {String}   cfg.prop: property name (if it is an Array of objects)
   * @property {Boolean}  cfg.desc: determines whether the sort is descending
   * @property {Function} cfg.parser: function to parse the items to expected type
   * @return {Array}
   */
  return function sortby (array, cfg) {
    if (!(array instanceof Array && array.length)) return [];
    if (toString.call(cfg) !== "[object Object]") cfg = {};
    if (typeof cfg.parser !== "function") cfg.parser = parse;
    cfg.desc = !!cfg.desc ? -1 : 1;
    return array.sort(function (a, b) {
      a = getItem.call(cfg, a);
      b = getItem.call(cfg, b);
      return cfg.desc * (a < b ? -1 : +(a > b));
    });
  };

}());

Ustawianie nieposortowanych danych

var data = [
  {date: "2011-11-14T16:30:43Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:22:59Z", quantity: 2, total: 90,  tip: 0,   type: "Tab"},
  {date: "2011-11-14T16:28:54Z", quantity: 1, total: 300, tip: 200, type: "visa"},
  {date: "2011-11-14T16:53:41Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:48:46Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:25:45Z", quantity: 2, total: 200, tip: 0,   type: "cash"},
  {date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"},
  {date: "2011-11-14T16:58:03Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:20:19Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-14T17:07:21Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0,   type: "Cash"}
];

Użyj tego

Rozmieszczanie tablicę, przez "date"coString

// sort by @date (ascending)
sortBy(data, { prop: "date" });

// expected: first element
// { date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab" }

// expected: last element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"}

Jeśli chcesz zignorować wielkość liter, ustaw parseroddzwonienie:

// sort by @type (ascending) IGNORING case-sensitive
sortBy(data, {
    prop: "type",
    parser: (t) => t.toUpperCase()
});

// expected: first element
// { date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0, type: "Cash" }

// expected: last element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa" }

Jeśli chcesz przekonwertować "date"pole jako Datetyp:

// sort by @date (descending) AS Date object
sortBy(data, {
    prop: "date",
    desc: true,
    parser: (d) => new Date(d)
});

// expected: first element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"}

// expected: last element
// { date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab" }

Tutaj możesz grać z kodem: jsbin.com/lesebi

Dzięki @Ozeshowi przez jego opinię problem związany z właściwościami z wartościami fałszowania został naprawiony.

jherax
źródło
Wydaje się, że pęka, gdy pole jest puste.
TSNev
Jeśli sortujesz liczby i napotykasz „0” między tablicą obiektów, możesz zauważyć, że powyższy kod się psuje. Oto krótka poprawka: var checkNaN = function (value) { return Number.isNaN(Number(value)) ? 0 : value; } po której następuje: funkcja return (tablica, o) { .... a = _getItem.call (o, a); a = checkNaN (a); b = _getItem.call (o, b); b = checkNaN (b); return o.desc * (a <b? -1: + (a> b)); });
Ozesh
18

Użyj lodash.sortBy , (instrukcje przy użyciu commonjs, możesz także po prostu umieścić skrypt include-tag dla cdn na górze html)

var sortBy = require('lodash.sortby');
// or
sortBy = require('lodash').sortBy;

Kolejność malejąca

var descendingOrder = sortBy( homes, 'price' ).reverse();

Rosnąco

var ascendingOrder = sortBy( homes, 'price' );
Evan Carroll
źródło
1
Lubconst sortBy = require('lodash/sortBy'); let calendars = sortBy(calendarListResponse.items, cal => cal.summary);
mpen
nie jestem pewien, czy loadash zmienił się ostatnio o nazwie OrderByimport { orderBy } from 'lodash'; ... ... return orderBy ( rows, 'fieldName' ).reverse();
montelof
8

Można to osiągnąć za pomocą prostej funkcji sortowania valueof () w jednym wierszu . Uruchom fragment kodu poniżej, aby zobaczyć wersję demonstracyjną.

var homes = [
    {
        "h_id": "3",
        "city": "Dallas",
        "state": "TX",
        "zip": "75201",
        "price": "162500"
    }, {
        "h_id": "4",
        "city": "Bevery Hills",
        "state": "CA",
        "zip": "90210",
        "price": "319250"
    }, {
        "h_id": "5",
        "city": "New York",
        "state": "NY",
        "zip": "00010",
        "price": "962500"
    }
];

console.log("To sort descending/highest first, use operator '<'");

homes.sort(function(a,b) { return a.price.valueOf() < b.price.valueOf();});

console.log(homes);

console.log("To sort ascending/lowest first, use operator '>'");

homes.sort(function(a,b) { return a.price.valueOf() > b.price.valueOf();});

console.log(homes);

Ajay Singh
źródło
8

Trochę się spóźniam na przyjęcie, ale poniżej moja logika sortowania.

function getSortedData(data, prop, isAsc) {
    return data.sort((a, b) => {
        return (a[prop] < b[prop] ? -1 : 1) * (isAsc ? 1 : -1)
    });
}
Santosh
źródło
6

Chociaż wiem, że OP chciał posortować tablicę liczb, pytanie to zostało oznaczone jako odpowiedź na podobne pytania dotyczące ciągów znaków. W związku z tym powyższe odpowiedzi nie uwzględniają sortowania tablicy tekstu, w której ważna jest wielkość liter. Większość odpowiedzi pobiera wartości ciągów i konwertuje je na wielkie / małe litery, a następnie sortuje w taki czy inny sposób. Wymagania, które stosuję, są proste:

  • Sortuj alfabetycznie AZ
  • Wielkie litery tego samego słowa powinny znajdować się przed wartościami małych liter
  • Te same wartości literowe (A / a, B / b) powinny być zgrupowane razem

Czego oczekuję, [ A, a, B, b, C, c ]ale odpowiedzi powyżej zwracają A, B, C, a, b, c. Właściwie podrapałem się po tym dłużej niż chciałem (dlatego piszę to w nadziei, że pomoże to przynajmniej jednej innej osobie). Podczas gdy dwóch użytkowników wspomina o localeComparefunkcji w komentarzach do zaznaczonej odpowiedzi, nie zauważyłem tego, dopóki nie natknąłem się na funkcję podczas wyszukiwania. Po przeczytaniu dokumentacji String.prototype.localeCompare () udało mi się wymyślić:

var values = [ "Delta", "charlie", "delta", "Charlie", "Bravo", "alpha", "Alpha", "bravo" ];
var sorted = values.sort((a, b) => a.localeCompare(b, undefined, { caseFirst: "upper" }));
// Result: [ "Alpha", "alpha", "Bravo", "bravo", "Charlie", "charlie", "Delta", "delta" ]

Mówi to funkcji, aby sortowała wartości pisane wielkimi literami przed wartościami pisanymi małymi literami. Drugim parametrem w tej localeComparefunkcji jest zdefiniowanie ustawień narodowych, ale jeśli je opuścisz undefined, automatycznie określa ono ustawienia narodowe.

Działa to również w przypadku sortowania tablicy obiektów:

var values = [
    { id: 6, title: "Delta" },
    { id: 2, title: "charlie" },
    { id: 3, title: "delta" },
    { id: 1, title: "Charlie" },
    { id: 8, title: "Bravo" },
    { id: 5, title: "alpha" },
    { id: 4, title: "Alpha" },
    { id: 7, title: "bravo" }
];
var sorted = values
    .sort((a, b) => a.title.localeCompare(b.title, undefined, { caseFirst: "upper" }));
Mitchell Skurnik
źródło
5

Możesz użyć sortmetody JavaScript z funkcją wywołania zwrotnego:

function compareASC(homeA, homeB)
{
    return parseFloat(homeA.price) - parseFloat(homeB.price);
}

function compareDESC(homeA, homeB)
{
    return parseFloat(homeB.price) - parseFloat(homeA.price);
}

// Sort ASC
homes.sort(compareASC);

// Sort DESC
homes.sort(compareDESC);
John G.
źródło
4

Oto kulminacja wszystkich powyższych odpowiedzi.

Sprawdzanie poprawności Fiddle: http://jsfiddle.net/bobberino/4qqk3/

var sortOn = function (arr, prop, reverse, numeric) {

    // Ensure there's a property
    if (!prop || !arr) {
        return arr
    }

    // Set up sort function
    var sort_by = function (field, rev, primer) {

        // Return the required a,b function
        return function (a, b) {

            // Reset a, b to the field
            a = primer(a[field]), b = primer(b[field]);

            // Do actual sorting, reverse as needed
            return ((a < b) ? -1 : ((a > b) ? 1 : 0)) * (rev ? -1 : 1);
        }

    }

    // Distinguish between numeric and string to prevent 100's from coming before smaller
    // e.g.
    // 1
    // 20
    // 3
    // 4000
    // 50

    if (numeric) {

        // Do sort "in place" with sort_by function
        arr.sort(sort_by(prop, reverse, function (a) {

            // - Force value to a string.
            // - Replace any non numeric characters.
            // - Parse as float to allow 0.02 values.
            return parseFloat(String(a).replace(/[^0-9.-]+/g, ''));

        }));
    } else {

        // Do sort "in place" with sort_by function
        arr.sort(sort_by(prop, reverse, function (a) {

            // - Force value to string.
            return String(a).toUpperCase();

        }));
    }


}
kok
źródło
czy możesz wyjaśnić, jakie jest znaczenie posiadania * (rev? -1: 1);
TechTurtle,
Ma to na celu odwrócenie kolejności (rosnąco lub malejąco) część obrotów po prostu odwraca normalne wyniki, gdy argument rev jest prawdziwy. W przeciwnym razie pomnoży się przez 1, co nie robi nic, po ustawieniu pomnoży wynik przez -1, odwracając w ten sposób wynik.
Bob
3

Pracowałem również z pewnego rodzaju oceną i sortowaniem wielu pól:

arr = [
    {type:'C', note:834},
    {type:'D', note:732},
    {type:'D', note:008},
    {type:'F', note:474},
    {type:'P', note:283},
    {type:'P', note:165},
    {type:'X', note:173},
    {type:'Z', note:239},
];

arr.sort(function(a,b){        
    var _a = ((a.type==='C')?'0':(a.type==='P')?'1':'2');
    _a += (a.type.localeCompare(b.type)===-1)?'0':'1';
    _a += (a.note>b.note)?'1':'0';
    var _b = ((b.type==='C')?'0':(b.type==='P')?'1':'2');
    _b += (b.type.localeCompare(a.type)===-1)?'0':'1';
    _b += (b.note>a.note)?'1':'0';
    return parseInt(_a) - parseInt(_b);
});

Wynik

[
    {"type":"C","note":834},
    {"type":"P","note":165},
    {"type":"P","note":283},
    {"type":"D","note":8},
    {"type":"D","note":732},
    {"type":"F","note":474},
    {"type":"X","note":173},
    {"type":"Z","note":239}
]
Rodolfo Jorge Nemer Nogueira
źródło
3

Podczas gdy sortowanie pojedynczej tablicy jest nieco przesadne, ta prototypowa funkcja pozwala sortować tablice JavaScript według dowolnego klucza, w kolejności rosnącej lub malejącej, w tym kluczy zagnieżdżonych , przy użyciu dotskładni.

(function(){
    var keyPaths = [];

    var saveKeyPath = function(path) {
        keyPaths.push({
            sign: (path[0] === '+' || path[0] === '-')? parseInt(path.shift()+1) : 1,
            path: path
        });
    };

    var valueOf = function(object, path) {
        var ptr = object;
        for (var i=0,l=path.length; i<l; i++) ptr = ptr[path[i]];
        return ptr;
    };

    var comparer = function(a, b) {
        for (var i = 0, l = keyPaths.length; i < l; i++) {
            aVal = valueOf(a, keyPaths[i].path);
            bVal = valueOf(b, keyPaths[i].path);
            if (aVal > bVal) return keyPaths[i].sign;
            if (aVal < bVal) return -keyPaths[i].sign;
        }
        return 0;
    };

    Array.prototype.sortBy = function() {
        keyPaths = [];
        for (var i=0,l=arguments.length; i<l; i++) {
            switch (typeof(arguments[i])) {
                case "object": saveKeyPath(arguments[i]); break;
                case "string": saveKeyPath(arguments[i].match(/[+-]|[^.]+/g)); break;
            }
        }
        return this.sort(comparer);
    };    
})();

Stosowanie:

var data = [
    { name: { first: 'Josh', last: 'Jones' }, age: 30 },
    { name: { first: 'Carlos', last: 'Jacques' }, age: 19 },
    { name: { first: 'Carlos', last: 'Dante' }, age: 23 },
    { name: { first: 'Tim', last: 'Marley' }, age: 9 },
    { name: { first: 'Courtney', last: 'Smith' }, age: 27 },
    { name: { first: 'Bob', last: 'Smith' }, age: 30 }
]

data.sortBy('age'); // "Tim Marley(9)", "Carlos Jacques(19)", "Carlos Dante(23)", "Courtney Smith(27)", "Josh Jones(30)", "Bob Smith(30)"

Sortowanie według zagnieżdżonych właściwości za pomocą składni kropkowej lub tablicowej:

data.sortBy('name.first'); // "Bob Smith(30)", "Carlos Dante(23)", "Carlos Jacques(19)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"
data.sortBy(['name', 'first']); // "Bob Smith(30)", "Carlos Dante(23)", "Carlos Jacques(19)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"

Sortowanie według wielu kluczy:

data.sortBy('name.first', 'age'); // "Bob Smith(30)", "Carlos Jacques(19)", "Carlos Dante(23)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"
data.sortBy('name.first', '-age'); // "Bob Smith(30)", "Carlos Dante(23)", "Carlos Jacques(19)", "Courtney Smith(27)", "Josh Jones(30)", "Tim Marley(9)"

Możesz rozwidlić repozytorium: https://github.com/eneko/Array.sortBy

Eneko Alonso
źródło
Bardzo podoba mi się ta odpowiedź ze względu na sortByzwięzłą składnię. Prosty w użyciu - nawet z zagnieżdżonymi polami - przy zachowaniu doskonałej czytelności kodu. Dziękuję Ci!
Manfred Urban
3

Dzięki ECMAScript 6 odpowiedź StoBor może być jeszcze bardziej zwięzła:

homes.sort((a, b) => a.price - b.price)
CracyD
źródło
3

Cena malejąca:

homes.sort((x,y) => {return y.price - x.price})

Rosnąco kolejność ceny:

homes.sort((x,y) => {return x.price - y.price})
Arushi Bajpai
źródło
2

Aby posortować tablicę, musisz zdefiniować funkcję komparatora. Ta funkcja zawsze różni się w zależności od pożądanego wzorca sortowania lub kolejności (tj. Rosnąco lub malejąco).

Pozwól, że utworzymy niektóre funkcje, które sortują tablicę rosnącą lub malejącą i która zawiera wartości obiektu lub łańcucha lub wartości liczbowe.

function sorterAscending(a,b) {
    return a-b;
}

function sorterDescending(a,b) {
    return b-a;
}

function sorterPriceAsc(a,b) {
    return parseInt(a['price']) - parseInt(b['price']);
}

function sorterPriceDes(a,b) {
    return parseInt(b['price']) - parseInt(b['price']);
}

Sortuj liczby (alfabetycznie i rosnąco):

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();

Sortuj liczby (alfabetycznie i malejąco):

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
fruits.reverse();

Sortuj liczby (numerycznie i rosnąco):

var points = [40,100,1,5,25,10];
points.sort(sorterAscending());

Sortuj liczby (numerycznie i malejąco):

var points = [40,100,1,5,25,10];
points.sort(sorterDescending());

Jak wyżej, użyj metody sorterPriceAsc i sorterPriceDes z tablicą z pożądanym kluczem.

homes.sort(sorterPriceAsc()) or homes.sort(sorterPriceDes())
Lalit Kumar Maurya
źródło
2

Jeśli używasz Underscore.js , spróbuj sortBy:

// price is of an integer type
_.sortBy(homes, "price"); 

// price is of a string type
_.sortBy(homes, function(home) {return parseInt(home.price);}); 
Vitalii Fedorenko
źródło
2

Oto nieco zmodyfikowana wersja eleganckiego wdrożenia z książki „JavaScript: dobre części”.

UWAGA : Ta wersja byjest stabilna . Zachowuje kolejność pierwszego sortowania podczas wykonywania następnego sortowania łańcuchowego.

Dodałem isAscendingdo niego parametr. Przekształciłem go również w ES6standardy i „nowsze” dobre części zgodnie z zaleceniami autora.

Możesz sortować rosnąco, malejąco i łańcuchowo według wielu właściwości.

const by = function (name, minor, isAscending=true) {
    const reverseMutliplier = isAscending ? 1 : -1;
    return function (o, p) {
        let a, b;
        let result;
        if (o && p && typeof o === "object" && typeof p === "object") {
            a = o[name];
            b = p[name];
            if (a === b) {
                return typeof minor === 'function' ? minor(o, p) : 0;
            }
            if (typeof a === typeof b) {
                result = a < b ? -1 : 1;
            } else {
                result = typeof a < typeof b ? -1 : 1;
            }
            return result * reverseMutliplier;
        } else {
            throw {
                name: "Error",
                message: "Expected an object when sorting by " + name
            };
        }
    };
};

let s = [
    {first: 'Joe',   last: 'Besser'},
    {first: 'Moe',   last: 'Howard'},
    {first: 'Joe',   last: 'DeRita'},
    {first: 'Shemp', last: 'Howard'},
    {first: 'Larry', last: 'Fine'},
    {first: 'Curly', last: 'Howard'}
];

// Sort by: first ascending, last ascending
s.sort(by("first", by("last")));    
console.log("Sort by: first ascending, last ascending: ", s);     // "[
//     {"first":"Curly","last":"Howard"},
//     {"first":"Joe","last":"Besser"},     <======
//     {"first":"Joe","last":"DeRita"},     <======
//     {"first":"Larry","last":"Fine"},
//     {"first":"Moe","last":"Howard"},
//     {"first":"Shemp","last":"Howard"}
// ]

// Sort by: first ascending, last descending
s.sort(by("first", by("last", 0, false)));  
console.log("sort by: first ascending, last descending: ", s);    // "[
//     {"first":"Curly","last":"Howard"},
//     {"first":"Joe","last":"DeRita"},     <========
//     {"first":"Joe","last":"Besser"},     <========
//     {"first":"Larry","last":"Fine"},
//     {"first":"Moe","last":"Howard"},
//     {"first":"Shemp","last":"Howard"}
// ]

mityczny koder
źródło
czy możemy posortować {"first":"Curly","last":"Howard", "property" : {"id" : "1"}}typ tablicy według identyfikatora?
Vishal Kumar Sahu
tak, funkcja musi zostać nieco zmodyfikowana, aby przyjąć nowy parametr, powiedzmy, nestedName. Następnie wywołujesz byz name = "property", nestedName = "id"
mythicalcoder
2

Tylko dla normalnej tablicy wartości elementów:

function sortArrayOfElements(arrayToSort) {
    function compareElements(a, b) {
        if (a < b)
            return -1;
        if (a > b)
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareElements);
}

e.g. 1:
var array1 = [1,2,545,676,64,2,24]
output : [1, 2, 2, 24, 64, 545, 676]

var array2 = ["v","a",545,676,64,2,"24"]
output: ["a", "v", 2, "24", 64, 545, 676]

W przypadku tablicy obiektów:

function sortArrayOfObjects(arrayToSort, key) {
    function compareObjects(a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    }

    return arrayToSort.sort(compareObjects);
}

e.g. 1: var array1= [{"name": "User4", "value": 4},{"name": "User3", "value": 3},{"name": "User2", "value": 2}]

output : [{"name": "User2", "value": 2},{"name": "User3", "value": 3},{"name": "User4", "value": 4}]
Umesh
źródło
2

Utwórz funkcję i sortuj na podstawie danych wejściowych, używając poniższego kodu

var homes = [{

    "h_id": "3",
    "city": "Dallas",
    "state": "TX",
    "zip": "75201",
    "price": "162500"

 }, {

    "h_id": "4",
    "city": "Bevery Hills",
    "state": "CA",
    "zip": "90210",
    "price": "319250"

 }, {

    "h_id": "5",
    "city": "New York",
    "state": "NY",
    "zip": "00010",
    "price": "962500"

 }];

 function sortList(list,order){
     if(order=="ASC"){
        return list.sort((a,b)=>{
            return parseFloat(a.price) - parseFloat(b.price);
        })
     }
     else{
        return list.sort((a,b)=>{
            return parseFloat(b.price) - parseFloat(a.price);
        });
     }
 }

 sortList(homes,'DESC');
 console.log(homes);
Andrew Rayan
źródło
2

Możesz użyć string1.localeCompare (string2) do porównania napisów

this.myArray.sort((a,b) => { 
    return a.stringProp.localeCompare(b.stringProp);
});

Zauważ, że localCompareto przypadek w czuły

bradvido
źródło
1

Do sortowania w polu obiektu z wieloma tablicami. Wpisz nazwę pola w arrproptablicy, jak ["a","b","c"] następnie podaj drugi parametr arrsourcerzeczywistego źródła, które chcemy posortować.

function SortArrayobject(arrprop,arrsource){
arrprop.forEach(function(i){
arrsource.sort(function(a,b){
return ((a[i] < b[i]) ? -1 : ((a[i] > b[i]) ? 1 : 0));
});
});
return arrsource;
}
Pradip Talavija
źródło
1

Będziesz potrzebował dwóch funkcji

function desc(a, b) {
 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}

function asc(a, b) {
  return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

Następnie możesz zastosować to do dowolnej właściwości obiektu:

 data.sort((a, b) => desc(parseFloat(a.price), parseFloat(b.price)));

let data = [
    {label: "one", value:10},
    {label: "two", value:5},
    {label: "three", value:1},
];

// sort functions
function desc(a, b) {
 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}

function asc(a, b) {
 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

// DESC
data.sort((a, b) => desc(a.value, b.value));

document.body.insertAdjacentHTML(
 'beforeend', 
 '<strong>DESCending sorted</strong><pre>' + JSON.stringify(data) +'</pre>'
);

// ASC
data.sort((a, b) => asc(a.value, b.value));

document.body.insertAdjacentHTML(
 'beforeend', 
 '<strong>ASCending sorted</strong><pre>' + JSON.stringify(data) +'</pre>'
);

OzzyCzech
źródło
0

Niedawno napisałem uniwersalną funkcję do zarządzania tym, jeśli chcesz z niej skorzystać.

/**
 * Sorts an object into an order
 *
 * @require jQuery
 *
 * @param object Our JSON object to sort
 * @param type Only alphabetical at the moment
 * @param identifier The array or object key to sort by
 * @param order Ascending or Descending
 *
 * @returns Array
 */
function sortItems(object, type, identifier, order){

    var returnedArray = [];
    var emptiesArray = []; // An array for all of our empty cans

    // Convert the given object to an array
    $.each(object, function(key, object){

        // Store all of our empty cans in their own array
        // Store all other objects in our returned array
        object[identifier] == null ? emptiesArray.push(object) : returnedArray.push(object);

    });

    // Sort the array based on the type given
    switch(type){

        case 'alphabetical':

            returnedArray.sort(function(a, b){

                return(a[identifier] == b[identifier]) ? 0 : (

                    // Sort ascending or descending based on order given
                    order == 'asc' ? a[identifier] > b[identifier] : a[identifier] < b[identifier]

                ) ? 1 : -1;

            });

            break;

        default:

    }

    // Return our sorted array along with the empties at the bottom depending on sort order
    return order == 'asc' ? returnedArray.concat(emptiesArray) : emptiesArray.concat(returnedArray);

}
Brad Bird
źródło
0
homes.sort(function(a, b){
  var nameA=a.prices.toLowerCase(), nameB=b.prices.toLowerCase()
  if (nameA < nameB) //sort string ascending
    return -1 
  if (nameA > nameB)
    return 1
  return 0 //default return value (no sorting)
})
użytkownik3346960
źródło
0

Cześć po przeczytaniu tego artykułu, stworzyłem sortComparator dla moich potrzeb, z funkcją porównywania więcej niż jednego atrybutu JSON i chcę się nim z Wami podzielić.

To rozwiązanie porównuje tylko ciągi w porządku rosnącym, ale rozwiązanie można łatwo rozszerzyć dla każdego obsługiwanego atrybutu: odwrotne uporządkowanie, inne typy danych, użycie ustawień regionalnych, rzutowanie itp.

var homes = [{

    "h_id": "3",
    "city": "Dallas",
    "state": "TX",
    "zip": "75201",
    "price": "162500"

}, {

    "h_id": "4",
    "city": "Bevery Hills",
    "state": "CA",
    "zip": "90210",
    "price": "319250"

}, {

    "h_id": "5",
    "city": "New York",
    "state": "NY",
    "zip": "00010",
    "price": "962500"

}];

// comp = array of attributes to sort
// comp = ['attr1', 'attr2', 'attr3', ...]
function sortComparator(a, b, comp) {
    // Compare the values of the first attribute
    if (a[comp[0]] === b[comp[0]]) {
        // if EQ proceed with the next attributes
        if (comp.length > 1) {
            return sortComparator(a, b, comp.slice(1));
        } else {
            // if no more attributes then return EQ
            return 0;
        }
    } else {
        // return less or great
        return (a[comp[0]] < b[comp[0]] ? -1 : 1)
    }
}

// Sort array homes
homes.sort(function(a, b) {
    return sortComparator(a, b, ['state', 'city', 'zip']);
});

// display the array
homes.forEach(function(home) {
    console.log(home.h_id, home.city, home.state, home.zip, home.price);
});

i wynik jest

$ node sort
4 Bevery Hills CA 90210 319250
5 New York NY 00010 962500
3 Dallas TX 75201 162500

i inny rodzaj

homes.sort(function(a, b) {
    return sortComparator(a, b, ['city', 'zip']);
});

z wynikiem

$ node sort
4 Bevery Hills CA 90210 319250
3 Dallas TX 75201 162500
5 New York NY 00010 962500
George Vrynios
źródło
0

Prosty kod:

    var homes = [
        {
            "h_id": "3",
            "city": "Dallas",
            "state": "TX",
            "zip": "75201",
            "price": "162500"
        }, {
            "h_id": "4",
            "city": "Bevery Hills",
            "state": "CA",
            "zip": "90210",
            "price": "319250"
        }, {
            "h_id": "5",
            "city": "New York",
            "state": "NY",
            "zip": "00010",
            "price": "962500"
        }
    ];

    let sortByPrice = homes.sort(function (a, b) 
    {
      return parseFloat(b.price) - parseFloat(a.price);
    });

    for (var i=0; i<sortByPrice.length; i++)
    {
      document.write(sortByPrice[i].h_id+' '+sortByPrice[i].city+' '
       +sortByPrice[i].state+' '
       +sortByPrice[i].zip+' '+sortByPrice[i].price);
      document.write("<br>");
    }

rashedcs
źródło
0
 function compareValues(key, order = 'asc') {
  return function innerSort(a, b) {
    if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) {
      // property doesn't exist on either object
      return 0;
    }

    const varA = (typeof a[key] === 'string')
      ? a[key].toUpperCase() : a[key];
    const varB = (typeof b[key] === 'string')
      ? b[key].toUpperCase() : b[key];

    let comparison = 0;
    if (varA > varB) {
      comparison = 1;
    } else if (varA < varB) {
      comparison = -1;
    }
    return (
      (order === 'desc') ? (comparison * -1) : comparison
    );
  };
}

http://yazilimsozluk.com/sort-array-in-javascript-by-asc-or-desc

użytkownik1688401
źródło