How to sort an array of objects by multiple fields?

后端 未结 30 3038
北恋
北恋 2020-11-21 11:34

From this original question, how would I apply a sort on multiple fields?

Using this slightly adapted structure, how would I sort city (ascending) & then price (

30条回答
  •  清歌不尽
    2020-11-21 12:15

    Adaptation of @chriskelly 's answer.


    Most answers overlook that price will not sort properly if the value is in the ten thousands and lower or over a million. The resaon being JS sorts alphabetically. It was answered pretty well here, Why can't JavaScript sort "5, 10, 1" and here How to sort an array of integers correctly.

    Ultimately we have to do some evaluation if the field or node we're sorting by is an number. I am not saying that using parseInt() in this case is the correct answer, the sorted results are more important.

    var homes = [{
      "h_id": "2",
      "city": "Dallas",
      "state": "TX",
      "zip": "75201",
      "price": "62500"
    }, {
      "h_id": "1",
      "city": "Dallas",
      "state": "TX",
      "zip": "75201",
      "price": "62510"
    }, {
      "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": "6",
      "city": "Dallas",
      "state": "TX",
      "zip": "75000",
      "price": "556699"
    }, {
      "h_id": "5",
      "city": "New York",
      "state": "NY",
      "zip": "00010",
      "price": "962500"
    }];
    
    homes.sort(fieldSorter(['price']));
    // homes.sort(fieldSorter(['zip', '-state', 'price'])); // alternative
    
    function fieldSorter(fields) {
      return function(a, b) {
        return fields
          .map(function(o) {
            var dir = 1;
            if (o[0] === '-') {
              dir = -1;
              o = o.substring(1);
            }
            if (!parseInt(a[o]) && !parseInt(b[o])) {
              if (a[o] > b[o]) return dir;
              if (a[o] < b[o]) return -(dir);
              return 0;
            } else {
              return dir > 0 ? a[o] - b[o] : b[o] - a[o];
            }
          })
          .reduce(function firstNonZeroValue(p, n) {
            return p ? p : n;
          }, 0);
      };
    }
    document.getElementById("output").innerHTML = '
    ' + JSON.stringify(homes, null, '\t') + '
    ';


    A fiddle to test with

提交回复
热议问题