Javascript 基于多个属性对对象数组进行排序

Javascript 基于多个属性对对象数组进行排序,javascript,arrays,object,recursion,javascript-objects,Javascript,Arrays,Object,Recursion,Javascript Objects,我试图根据对象内部的任意属性对对象数组进行排序。 我编写了下面的代码,它工作得非常好。 var customSort=函数(数据、排序、顺序){ 如果(!(数据和排序)){ 抛出新错误('指定数据源和至少一个属性进行排序'); } 如果(!Array.isArray(数据)){ 抛出新错误(“将数据源指定为数组”); } 订单=订单| |‘asc’; 功能performSort(订单、排序){ 返回数据。排序(函数(a,b){ var A=解析(A,sortBy); var B=解析(B,so

我试图根据对象内部的任意属性对对象数组进行排序。 我编写了下面的代码,它工作得非常好。

var customSort=函数(数据、排序、顺序){
如果(!(数据和排序)){
抛出新错误('指定数据源和至少一个属性进行排序');
}
如果(!Array.isArray(数据)){
抛出新错误(“将数据源指定为数组”);
}
订单=订单| |‘asc’;
功能performSort(订单、排序){
返回数据。排序(函数(a,b){
var A=解析(A,sortBy);
var B=解析(B,sortBy);
if(AB){
退货订单=='asc'?1:-1;
}否则{
返回0;
}
});
}
函数解析(数据,排序){
var sortParams=排序方式拆分('.');
var latestValue=数据;
对于(变量i=0;i
在这里拉小提琴:




现在,我尝试使用递归以如下方式对多个属性进行排序:首先,按第一个属性排序,然后在同一个属性内,按第二个属性排序,依此类推。为了简单起见,我假设所有属性的顺序都相同,即要么全部递增,要么全部递减。
我编写了以下代码:

var customSort = function(data, sortBy, order) {
  if (!(data && sortBy)) {
    throw new Error('Specify the data source and atleast one property to sort it by');
  }
  if (!Array.isArray(data)) {
    throw new Error('Specify the data source as an array');
  }
  if (!Array.isArray(sortBy)) {
    sortBy = [sortBy];
  }
  order = order || 'asc';

  function performSort(order, sortBy) {
    return data.sort(function(a, b) {
      function nestedSort() {
        var highestOrder = sortBy[0];
        var A = parse(a, highestOrder);
        var B = parse(b, highestOrder);
        if (A < B) {
          return order === 'asc' ? -1 : 1;
        } else if (A > B) {
          return order === 'asc' ? 1 : -1;
        } else {
          sortBy.shift();
          nestedSort();
        }
      }
      return nestedSort();
    });
  }

  function parse(data, sortBy) {
    var sortParams = sortBy.split('.');
    var latestValue = data;
    for (var i = 0; i < sortParams.length; i++) {
      latestValue = latestValue[sortParams[i]];
    }
    if (!latestValue) {
      throw new Error('Check the \'sortBy\' parameter. Unreachable property passed in \'sortBy\'');
    }
    if (typeof latestValue === 'string') {
      return latestValue.toLowerCase();
    } else {
      return latestValue;
    }
  }

  return performSort(order, sortBy);
};

var lonelyData = [{
  a: {
    b: 2,
    c: 'Z'
  }
}, {
  a: {
    b: 2,
    c: 'A'
  }
}, {
  a: {
    b: 9,
    c: 'Q'
  }
}, {
  a: {
    b: 7,
    c: 'L'
  }
}, {
  a: {
    b: 7,
    c: 'E'
  }
}, {
  a: {
    b: 1,
    c: 'A'
  }
}, {
  a: {
    b: 1,
    c: 'B'
  }
}];

console.log(customSort(lonelyData, ['a.b', 'a.c']));
var customSort=函数(数据、排序、顺序){
如果(!(数据和排序)){
抛出新错误('指定数据源和至少一个属性进行排序');
}
如果(!Array.isArray(数据)){
抛出新错误(“将数据源指定为数组”);
}
if(!Array.isArray(sortBy)){
sortBy=[sortBy];
}
订单=订单| |‘asc’;
功能performSort(订单、排序){
返回数据。排序(函数(a,b){
函数nestedSort(){
var highestOrder=sortBy[0];
var A=解析(A,高阶);
var B=解析(B,高阶);
if(AB){
退货订单=='asc'?1:-1;
}否则{
sortBy.shift();
嵌套排序();
}
}
返回nestedSort();
});
}
函数解析(数据,排序){
var sortParams=排序方式拆分('.');
var latestValue=数据;
对于(变量i=0;i
在这里拉小提琴:


不幸的是,我不能让它工作。我错过了什么

这是你的问题
shift
会改变数组,并永远删除第一项。下次调用比较函数来比较
a
b
,它将被忽略,很快数组将为空,比较将完全中断

相反,使用一个简单的循环:

return data.sort(function(a, b) {
  for (var i=0; i<sortBy.length; i++)
    var currentOrder = sortBy[i];
    var A = parse(a, currentOrder);
    var B = parse(b, currentOrder);
    if (A < B) {
      return order === 'asc' ? -1 : 1;
    } else if (A > B) {
      return order === 'asc' ? 1 : -1;
    }
  }
  return 0;
});
返回数据。排序(函数(a,b){
对于(变量i=0;i B){
退货订单=='asc'?1:-1;
}
}
返回0;
});

这里有点混乱……如果排序比是[A.b,A.c],那么您希望数组按数字排序,然后按字母顺序排序?@LucasKot Zaniewski如果排序比是[A.b,A.c],那么数组应该按数字排序(基于A.b),然后对于相同的数字值(A.b),数组应该按字母顺序排序(基于A.c)。例如,它应该像:[{a:{b:1,c:'a'},{a:{b:1,c:'b'},{a:{b:2,c:'a'},{a:{b:2,c:'Z'}等等]对于上面的测试用例,非常感谢。它工作得很好。然而,它也可以递归吗?当然,只要在
i
上递归即可。或者通过
数组和
.slice(1)
循环执行
排序,以获得不带第一个元素的副本。别忘了你的基本情况!
     sortBy.shift();
     nestedSort();
return data.sort(function(a, b) {
  for (var i=0; i<sortBy.length; i++)
    var currentOrder = sortBy[i];
    var A = parse(a, currentOrder);
    var B = parse(b, currentOrder);
    if (A < B) {
      return order === 'asc' ? -1 : 1;
    } else if (A > B) {
      return order === 'asc' ? 1 : -1;
    }
  }
  return 0;
});