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

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

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.

其他回答

以下是@ snowburn的解决方案的通用版本:

var sortarray = [{field:'city', direction:'asc'}, {field:'price', direction:'desc'}];
array.sort(function(a,b){
    for(var i=0; i<sortarray.length; i++){
        retval = a[sortarray[i].field] < b[sortarray[i].field] ? -1 : a[sortarray[i].field] > b[sortarray[i].field] ? 1 : 0;
        if (sortarray[i].direction == "desc") {
            retval = retval * -1;
        }
        if (retval !== 0) {
            return retval;
        }
    }
}


})

这是基于我正在使用的排序例程。我没有测试这个特定的代码,所以它可能有错误,但你知道的。其思想是基于第一个表示差异的字段进行排序,然后停止并转到下一个记录。因此,如果您按三个字段排序,并且compare中的第一个字段足以确定正在排序的两个记录的排序顺序,那么将返回该排序结果并转到下一个记录。

我在5000条记录上测试了它(实际上使用了更复杂的排序逻辑),它在眨眼之间就做到了。如果实际向客户端加载超过1000条记录,则可能应该使用服务器端排序和过滤。

这段代码不区分大小写,我把它留给读者来处理这个微不足道的修改。

今天我做了一个相当通用的多特征排序器。你可以在这里看看byjs: https://github.com/Teun/thenBy.js

它允许您使用标准数组。排序,但使用firstBy(). thenby (). thenby()样式。它比上面发布的解决方案少了很多代码和复杂性。

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

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.

为什么复杂化?只需要整理两次!这是完美的: (只要确保将重要性顺序从低到高颠倒过来就行了):

jj.sort( (a, b) => (a.id >= b.id) ? 1 : -1 );
jj.sort( (a, b) => (a.status >= b.status) ? 1 : -1 );
// custom sorting by city
const sortArray = ['Dallas', 'New York', 'Beverly Hills'];

const sortData = (sortBy) =>
  data
    .sort((a, b) => {
      const aIndex = sortBy.indexOf(a.city);
      const bIndex = sortBy.indexOf(b.city);

      if (aIndex < bIndex) {
        return -1;
      }

      if (aIndex === bIndex) {
        // price descending
        return b.price- a.price;
      }

      return 1;
    });

sortData(sortArray);