下划线:基于多个属性的 sortBy()

2022-08-30 05:00:28

我正在尝试根据多个属性对包含对象的数组进行排序。即,如果第一个属性在两个对象之间是相同的,则应使用第二个属性来组合这两个对象。例如,请考虑以下数组:

var patients = [
             [{name: 'John', roomNumber: 1, bedNumber: 1}],
             [{name: 'Lisa', roomNumber: 1, bedNumber: 2}],
             [{name: 'Chris', roomNumber: 2, bedNumber: 1}],
             [{name: 'Omar', roomNumber: 3, bedNumber: 1}]
               ];

按属性对这些进行排序,我将使用以下代码:roomNumber

var sortedArray = _.sortBy(patients, function(patient) {
    return patient[0].roomNumber;
});

这工作正常,但是我该如何继续,以便“约翰”和“丽莎”将正确排序?


答案 1

sortBy说它是一个稳定的排序算法,所以你应该能够首先按第二个属性排序,然后按你的第一个属性再次排序,如下所示:

var sortedArray = _(patients).chain().sortBy(function(patient) {
    return patient[0].name;
}).sortBy(function(patient) {
    return patient[0].roomNumber;
}).value();

当第二个发现约翰和丽莎有相同的房间号时,它会按照找到它们的顺序保持他们,第一个设置为“丽莎,约翰”。sortBysortBy


答案 2

以下是我在这些情况下有时会使用的一个技巧:以这样一种方式组合属性,使结果可以排序:

var sortedArray = _.sortBy(patients, function(patient) {
  return [patient[0].roomNumber, patient[0].name].join("_");
});

但是,正如我所说,这很棘手。要正确地做到这一点,你可能希望实际使用核心JavaScript排序方法

patients.sort(function(x, y) {
  var roomX = x[0].roomNumber;
  var roomY = y[0].roomNumber;
  if (roomX !== roomY) {
    return compare(roomX, roomY);
  }
  return compare(x[0].name, y[0].name);
});

// General comparison function for convenience
function compare(x, y) {
  if (x === y) {
    return 0;
  }
  return x > y ? 1 : -1;
}

当然,这会就地对数组进行排序。如果你想要一个排序的副本(就像给你的一样),先克隆数组:_.sortBy

function sortOutOfPlace(sequence, sorter) {
  var copy = _.clone(sequence);
  copy.sort(sorter);
  return copy;
}

出于无聊,我刚刚为此编写了一个通用解决方案(按任意数量的键排序):看看