JavaScript 如何根据字符串属性值对对象数组排序

在处理 JavaScript 对象数组时,特别是当对象有复杂嵌套结构时,对数组进行排序可能会变得复杂。本文将介绍一种通用的方法来根据对象属性值对对象数组进行排序,包括处理嵌套对象的情形。

解决方案总结

本文提供的方法是基于 @ege-ÖzcanStackOverflow 上的回答。我们将通过编写一个通用的函数 dynamicMultiSort 来实现对象数组的多级排序。

问题描述

假设我们有以下数据结构 People

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename: "Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

我们的目标是首先根据 People.Name.name 排序,然后根据 People.Name.surname 进行次级排序。

挑战

我们希望实现动态属性访问,如果直接使用对象访问器 People['Name.name'] 是无效的,People['Name']['name'] 则是静态方法,我们希望的是更具动态性的解决方案。

解决方案详解

通过递归访问对象的属性,我们可以实现对嵌套对象的排序。下面是完整的代码实现及步骤讲解。

数据准备

首先,我们定义好需要排序的对象数组:

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename: "Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

多级排序函数

我们将实现 dynamicMultiSort 函数,该函数用于多级排序:

function dynamicMultiSort() {
  var args = Array.prototype.slice.call(arguments);
  
  return function (a, b) {
    var i = 0, result = 0, numberOfProperties = args.length;
    while(result === 0 && i < numberOfProperties) {
      result = dynamicSort(args[i])(a, b);
      i++;
    }
    return result;
  }
}

动态排序函数

利用 dynamicSort 实现针对单个属性的排序,该函数还负责确定排序顺序(升序或降序):

function dynamicSort(properties) {
  var sortOrder = 1;
  if(properties[properties.length - 1][0] === "-") {
    sortOrder = -1;
    properties[properties.length - 1] = properties[properties.length - 1].substr(1);
  }
  return function (a,b) {
    var propertyOfA = recurseObjProp(a, properties)
    var propertyOfB = recurseObjProp(b, properties)
    var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
    return result * sortOrder;
  };
}

递归属性访问函数

实现 recurseObjProp 函数,用于递归访问对象属性,直到访问到目标叶子节点:

function recurseObjProp(root, leafs, index) {
  index = index || 0;
  var upper = root;
  var lower = upper[leafs[index]];

  if (!lower) {
    return upper;
  }
  index++;
  return recurseObjProp(lower, leafs, index);
}

实现全部代码

结合上述方法,下面是完整的代码实现:

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

People.sort(dynamicMultiSort(['Name', 'name'], ['Name', '-surname']));

console.log(People);

function dynamicMultiSort() {
  var args = Array.prototype.slice.call(arguments);
  
  return function (a, b) {
    var i = 0, result = 0, numberOfProperties = args.length;
    while(result === 0 && i < numberOfProperties) {
      result = dynamicSort(args[i])(a, b);
      i++;
    }
    return result;
  }
}

function dynamicSort(properties) {
  var sortOrder = 1;
  if(properties[properties.length - 1][0] === "-") {
    sortOrder = -1;
    properties[properties.length - 1] = properties[properties.length - 1].substr(1);
  }
  return function (a,b) {
    var propertyOfA = recurseObjProp(a, properties);
    var propertyOfB = recurseObjProp(b, properties);
    var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
    return result * sortOrder;
  };
}

function recurseObjProp(root, leafs, index) {
  index = index || 0;
  var upper = root;
  var lower = upper[leafs[index]];

  if (!lower) {
    return upper;
  }
  index++;
  return recurseObjProp(lower, leafs, index);
}

结果验证

执行该代码后,People 数组将会被正确排序:

[
  { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
  { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' },
  { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' }
]

可以看到,数组首先按照 Name.name 排序,再次级按 Name.surname 排序。

总结

本文介绍了如何在 JavaScript 中根据对象的嵌套属性对对象数组进行排序。通过实现通用的 dynamicMultiSort 函数,我们可以实现具有高度灵活性的排序功能,无需引入第三方库。对复杂数据结构进行排序是许多开发场景中常见的需求,掌握这种通用解决方案可以提高代码的复用性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JKooll

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值