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

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

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

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

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


当前回答

function sortMultiFields(prop){
    return function(a,b){
        for(i=0;i<prop.length;i++)
        {
            var reg = /^\d+$/;
            var x=1;
            var field1=prop[i];
            if(prop[i].indexOf("-")==0)
            {
                field1=prop[i].substr(1,prop[i].length);
                x=-x;
            }

            if(reg.test(a[field1]))
            {
                a[field1]=parseFloat(a[field1]);
                b[field1]=parseFloat(b[field1]);
            }
            if( a[field1] > b[field1])
                return x;
            else if(a[field1] < b[field1])
                return -x;
        }
    }
}

如果你想按降序排序特定字段,如何使用(在字段前放-(减号)号)

homes.sort(sortMultiFields(["city","-price"]));

使用上面的函数,你可以对带有多个字段的json数组进行排序。根本不需要改变函数体

其他回答

这是一个递归算法,按多个字段排序,同时有机会在比较之前格式化值。

var data = [
{
    "id": 1,
    "ship": null,
    "product": "Orange",
    "quantity": 7,
    "price": 92.08,
    "discount": 0
},
{
    "id": 2,
    "ship": "2017-06-14T23:00:00.000Z".toDate(),
    "product": "Apple",
    "quantity": 22,
    "price": 184.16,
    "discount": 0
},
...
]
var sorts = ["product", "quantity", "ship"]

// comp_val formats values and protects against comparing nulls/undefines
// type() just returns the variable constructor
// String.lower just converts the string to lowercase.
// String.toDate custom fn to convert strings to Date
function comp_val(value){
    if (value==null || value==undefined) return null
    var cls = type(value)
    switch (cls){
        case String:
            return value.lower()
    }
    return value
}

function compare(a, b, i){
    i = i || 0
    var prop = sorts[i]
    var va = comp_val(a[prop])
    var vb = comp_val(b[prop])

    // handle what to do when both or any values are null
    if (va == null || vb == null) return true

    if ((i < sorts.length-1) && (va == vb)) {
        return compare(a, b, i+1)
    } 
    return va > vb
}

var d = data.sort(compare);
console.log(d);

如果a和b相等,它将尝试下一个字段,直到没有可用字段。

// 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);

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

jj.sort( (a, b) => (a.id >= b.id) ? 1 : -1 );
jj.sort( (a, b) => (a.status >= b.status) ? 1 : -1 );

我一直在寻找类似的东西,最后得到了这个:

首先,我们有一个或多个排序函数,总是返回0、1或-1:

const sortByTitle = (a, b): number => 
  a.title === b.title ? 0 : a.title > b.title ? 1 : -1;

您可以为想要排序的其他属性创建更多函数。

然后我有一个函数将这些排序函数合并为一个:

const createSorter = (...sorters) => (a, b) =>
  sorters.reduce(
    (d, fn) => (d === 0 ? fn(a, b) : d),
    0
  );

这可以用来以一种可读的方式组合上述排序函数:

const sorter = createSorter(sortByTitle, sortByYear)

items.sort(sorter)

当一个排序函数返回0时,将调用下一个排序函数进行进一步排序。

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

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