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

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

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

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

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


当前回答

只需遵循排序标准列表

即使要封装36个排序标准,这段代码也将始终保持可读和可理解

Nina在这里提出的解决方案当然非常优雅,但它意味着要知道在布尔逻辑中,值为0对应的值为false,并且布尔测试在JavaScript中可以返回除true / false以外的值(这里是数值),这对于初学者来说总是令人困惑。

还要考虑谁需要维护您的代码。也许会是你:想象一下你自己花了几天的时间在另一个人的代码上,然后有了一个有害的错误……你读了几千行充满技巧的文章,都累坏了

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 fSort = (a,b) => { let Dx = a.city.localeCompare(b.city) // 1st criteria if (Dx===0) Dx = Number(b.price) - Number(a.price) // 2nd // if (Dx===0) Dx = ... // 3rd // if (Dx===0) Dx = ... // 4th.... return Dx } console.log( homes.sort(fSort))

其他回答

下面是我基于施瓦兹变换的解决方案,希望你觉得有用。

function sortByAttribute(array, ...attrs) {
  // generate an array of predicate-objects contains
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // schwartzian transform idiom implementation. aka: "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i]) result = -1;
      if (o1.compareValues[i] > o2.compareValues[i]) result = 1;
      if (result *= predicates[i].descend) break;
    }
    return result;
  })
  .map(item => item.src);
}

下面是一个如何使用它的例子:

let games = [
  { name: 'Pako',              rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// sort by one attribute
console.log(sortByAttribute(games, 'name'));
// sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

以下是我的简历,请参考,并举例说明:

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

哇,这里有一些复杂的解。如此复杂,我决定想出一些更简单但也相当强大的东西。在这里;

function sortByPriority(data, priorities) {
  if (priorities.length == 0) {
    return data;
  }

  const nextPriority = priorities[0];
  const remainingPriorities = priorities.slice(1);

  const matched = data.filter(item => item.hasOwnProperty(nextPriority));
  const remainingData = data.filter(item => !item.hasOwnProperty(nextPriority));

  return sortByPriority(matched, remainingPriorities)
    .sort((a, b) => (a[nextPriority] > b[nextPriority]) ? 1 : -1)
    .concat(sortByPriority(remainingData, remainingPriorities));
}

这里有一个如何使用它的例子。

const data = [
  { id: 1,                         mediumPriority: 'bbb', lowestPriority: 'ggg' },
  { id: 2, highestPriority: 'bbb', mediumPriority: 'ccc', lowestPriority: 'ggg' },
  { id: 3,                         mediumPriority: 'aaa', lowestPriority: 'ggg' },
];

const priorities = [
  'highestPriority',
  'mediumPriority',
  'lowestPriority'
];


const sorted = sortByPriority(data, priorities);

这将首先根据属性的优先级排序,然后根据属性的值进行排序。

您可以使用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'])

通过添加两个辅助函数,可以简单地解决这类问题。sortByKey接受一个数组和一个函数,该函数应返回一个项目列表,用于与每个数组条目进行比较。

这利用了javascript对简单值的数组进行智能比较的事实,即[2]<[2,0]<[2,1]<[10,0]。

// Two helpers: function cmp(a, b) { if (a > b) { return 1 } else if (a < b) { return -1 } else { return 0 } } function sortByKey(arr, key) { arr.sort((a, b) => cmp(key(a), key(b))) } // A demonstration: let arr = [{a:1, b:2}, {b:3, a:0}, {a:1, b:1}, {a:2, b:2}, {a:2, b:1}, {a:1, b:10}] sortByKey(arr, item => [item.a, item.b]) console.log(JSON.stringify(arr)) // '[{"b":3,"a":0},{"a":1,"b":1},{"a":1,"b":10},{"a":1,"b":2},{"a":2,"b":1},{"a":2,"b":2}]' sortByKey(arr, item => [item.b, item.a]) console.log(JSON.stringify(arr)) // '[{"a":1,"b":1},{"a":2,"b":1},{"a":1,"b":10},{"a":1,"b":2},{"a":2,"b":2},{"b":3,"a":0}]'

我从Python的列表中偷取了这个想法。排序功能。