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

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

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 msort(arr, ...compFns) {
  let fn = compFns[0];
  arr = [].concat(arr);
  let arr1 = [];
  while (arr.length > 0) {
    let arr2 = arr.splice(0, 1);
    for (let i = arr.length; i > 0;) {
      if (fn(arr2[0], arr[--i]) === 0) {
        arr2 = arr2.concat(arr.splice(i, 1));
      }
    }
    arr1.push(arr2);
  }

  arr1.sort(function (a, b) {
    return fn(a[0], b[0]);
  });

  compFns = compFns.slice(1);
  let res = [];
  arr1.map(a1 => {
    if (compFns.length > 0) a1 = msort(a1, ...compFns);
    a1.map(a2 => res.push(a2));
  });
  return res;
}

let tstArr = [{ id: 1, sex: 'o' }, { id: 2, sex: 'm' }, { id: 3, sex: 'm' }, { id: 4, sex: 'f' }, { id: 5, sex: 'm' }, { id: 6, sex: 'o' }, { id: 7, sex: 'f' }];

function tstFn1(a, b) {
  if (a.sex > b.sex) return 1;
  else if (a.sex < b.sex) return -1;
  return 0;
}

function tstFn2(a, b) {
  if (a.id > b.id) return -1;
  else if (a.id < b.id) return 1;
  return 0;
}

console.log(JSON.stringify(msort(tstArr, tstFn1, tstFn2)));
//output:
//[{"id":7,"sex":"f"},{"id":4,"sex":"f"},{"id":5,"sex":"m"},{"id":3,"sex":"m"},{"id":2,"sex":"m"},{"id":6,"sex":"o"},{"id":1,"sex":"o"}]

其他回答

对于你的具体问题,一个非通用的,简单的解决方案:

homes.sort(
   function(a, b) {          
      if (a.city === b.city) {
         // Price is only important when cities are the same
         return b.price - a.price;
      }
      return a.city > b.city ? 1 : -1;
   });

一种多维排序方法,基于这个答案:

更新:这是一个“优化”版本。它做了更多的预处理,并预先为每个排序选项创建了一个比较函数。它可能需要更多的内存(因为它为每个排序选项存储了一个函数,但它应该更好一点,因为它不必在比较期间确定正确的设置。不过我没有做过任何侧写。

var sort_by;

(function() {
    // utility functions
    var default_cmp = function(a, b) {
            if (a == b) return 0;
            return a < b ? -1 : 1;
        },
        getCmpFunc = function(primer, reverse) {
            var dfc = default_cmp, // closer in scope
                cmp = default_cmp;
            if (primer) {
                cmp = function(a, b) {
                    return dfc(primer(a), primer(b));
                };
            }
            if (reverse) {
                return function(a, b) {
                    return -1 * cmp(a, b);
                };
            }
            return cmp;
        };

    // actual implementation
    sort_by = function() {
        var fields = [],
            n_fields = arguments.length,
            field, name, reverse, cmp;

        // preprocess sorting options
        for (var i = 0; i < n_fields; i++) {
            field = arguments[i];
            if (typeof field === 'string') {
                name = field;
                cmp = default_cmp;
            }
            else {
                name = field.name;
                cmp = getCmpFunc(field.primer, field.reverse);
            }
            fields.push({
                name: name,
                cmp: cmp
            });
        }

        // final comparison function
        return function(A, B) {
            var a, b, name, result;
            for (var i = 0; i < n_fields; i++) {
                result = 0;
                field = fields[i];
                name = field.name;

                result = field.cmp(A[name], B[name]);
                if (result !== 0) break;
            }
            return result;
        }
    }
}());

使用示例:

homes.sort(sort_by('city', {name:'price', primer: parseInt, reverse: true}));

DEMO


最初的功能:

var sort_by = function() {
   var fields = [].slice.call(arguments),
       n_fields = fields.length;

   return function(A,B) {
       var a, b, field, key, primer, reverse, result, i;

       for(i = 0; i < n_fields; i++) {
           result = 0;
           field = fields[i];

           key = typeof field === 'string' ? field : field.name;

           a = A[key];
           b = B[key];

           if (typeof field.primer  !== 'undefined'){
               a = field.primer(a);
               b = field.primer(b);
           }

           reverse = (field.reverse) ? -1 : 1;

           if (a<b) result = reverse * -1;
           if (a>b) result = reverse * 1;
           if(result !== 0) break;
       }
       return result;
   }
};

DEMO

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

 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"} ]; function sortBy(ar) { return ar.sort((a, b) => a.city === b.city ? b.price.toString().localeCompare(a.price) : a.city.toString().localeCompare(b.city)); } console.log(sortBy(homes));

您可以使用链式排序方法,取值的增量,直到它达到不等于零的值。

var data = [{ 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" }]; data.sort(function (a, b) { return a.city.localeCompare(b.city) || b.price - a.price; }); console.log(data); .as-console-wrapper { max-height: 100% !important; top: 0; }

或者,使用es6,简单地:

data.sort((a, b) => a.city.localeCompare(b.city) || b.price - a.price);