- Published on
对象数组按照字符串属性值排序
- Authors
- Name
在处理复杂数据结构时,例如对象数组,常常需要根据嵌套的属性值进行排序。本文将详细介绍如何实现这一功能,包括各个函数的具体实现步骤。
问题描述
我们遇到了如下的数据结构,需要对其进行排序。我们不希望临时展平对象,也不打算使用像 underscore
或 lodash
这样的库,主要是出于性能考虑以及为了实现的乐趣。
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']
是静态的,仅允许你深入到第 n 级。
解决方案
为了实现目标,我们需要遍历对象树并确定最终叶节点的值,同时也要处理任何中间叶节点。
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']))
// 结果是:
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
// { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
// { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]
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)
}
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
}
}
示例
可在 JSBin 上查看工作示例。