从这个最初的问题,我将如何在多个字段应用排序?

使用这种稍作调整的结构,我将如何排序城市(上升)和价格(下降)?

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":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];

我喜欢的事实是,给出的答案提供了一个一般的方法。在我计划使用这段代码的地方,我将不得不对日期以及其他东西进行排序。“启动”对象的能力似乎很方便,如果不是有点麻烦的话。

我试图把这个答案构建成一个很好的通用示例,但我运气不太好。


当前回答

下面是一种可扩展的按多个字段排序的方法。

homes.sort(function(left, right) {
    var city_order = left.city.localeCompare(right.city);
    var price_order = parseInt(left.price) - parseInt(right.price);
    return city_order || -price_order;
});

笔记

A function passed to array sort is expected to return negative, zero, positive to indicate less, equal, greater. a.localeCompare(b) is universally supported for strings, and returns -1,0,1 if a<b,a==b,a>b. Subtraction works on numeric fields, because a - b gives -,0,+ if a<b,a==b,a>b. || in the last line gives city priority over price. Negate to reverse order in any field, as in -price_order Add new fields to the or-chain: return city_order || -price_order || date_order; Date compare with subtraction, because date math converts to milliseconds since 1970.var date_order = new Date(left.date) - new Date(right.date); Boolean compare with subtraction, which is guaranteed to turn true and false to 1 and 0 (therefore the subtraction produces -1 or 0 or 1). var goodness_order = Boolean(left.is_good) - Boolean(right.is_good)This is unusual enough that I'd suggest drawing attention with the Boolean constructor, even if they're already boolean.

其他回答

改编自@chriskelly的回答。


大多数答案都忽略了,如果价值在1万美元以下或超过100万美元,价格将无法正确排序。原因是JS按字母顺序排序。这里回答得很好,为什么JavaScript不能对“5,10,1”排序,这里如何正确地对整数数组排序。

最后,如果我们要排序的字段或节点是一个数字,我们必须做一些计算。我并不是说在这种情况下使用parseInt()是正确的答案,排序结果更重要。

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 = '<pre>' + JSON.stringify(homes, null, '\t') + '</pre>'; <div id="output"> </div>


用来测试的小提琴

按多个字段排序对象数组的最简单方法:

 let 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":"6",
   "city":"Dallas",
   "state":"TX",
   "zip":"75000",
   "price":"556699"},
  {"h_id":"5",
   "city":"New York",
   "state":"NY",
   "zip":"00010",
   "price":"962500"}
  ];

homes.sort((a, b) => (a.city > b.city) ? 1 : -1);

输出: “Bevery山” “达拉斯” “达拉斯” “达拉斯” “纽约”

这里有一个简单的泛型函数方法。使用数组指定排序顺序。前置减号以指定降序。

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":"6", "city":"Dallas", "state":"TX", "zip":"75000", "price":"556699"},
    {"h_id":"5", "city":"New York", "state":"NY", "zip":"00010", "price":"962500"}
    ];

homes.sort(fieldSorter(['city', '-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 (a[o] > b[o]) return dir;
                if (a[o] < b[o]) return -(dir);
                return 0;
            })
            .reduce(function firstNonZeroValue (p,n) {
                return p ? p : n;
            }, 0);
    };
}

编辑:在ES6中它甚至更短!

"use strict"; const fieldSorter = (fields) => (a, b) => fields.map(o => { let dir = 1; if (o[0] === '-') { dir = -1; o=o.substring(1); } return a[o] > b[o] ? dir : a[o] < b[o] ? -(dir) : 0; }).reduce((p, n) => p ? p : n, 0); 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":"6", "city":"Dallas", "state":"TX", "zip":"75000", "price":556699},{"h_id":"5", "city":"New York", "state":"NY", "zip":"00010", "price":962500}]; const sortedHomes = homes.sort(fieldSorter(['state', '-price'])); document.write('<pre>' + JSON.stringify(sortedHomes, null, '\t') + '</pre>')

下面这个简单的解决方案怎么样:

const sortCompareByCityPrice = (a, b) => {
    let comparison = 0
    // sort by first criteria
    if (a.city > b.city) {
        comparison = 1
    }
    else if (a.city < b.city) {
        comparison = -1
    }
    // If still 0 then sort by second criteria descending
    if (comparison === 0) {
        if (parseInt(a.price) > parseInt(b.price)) {
            comparison = -1
        }
        else if (parseInt(a.price) < parseInt(b.price)) {
            comparison = 1
        }
    }
    return comparison 
}

基于这个问题javascript排序数组的多个(数字)字段

您可以使用lodash或derby函数lodash

它有两个参数字段数组和方向数组('asc','desc')

  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":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];

var sorted =. data._.orderBy(data, ['city', 'price'], ['asc','desc'])