복잡한 객체 배열 정렬 (추가)
이 배열과 같은 더 복잡한 데이터 구조가 발생할 수 있으므로 솔루션을 확장 할 것입니다.
TL; DR
더 플러그 버전을 기반으로 @ EGE-Özcan '매우 사랑이야 대답 .
문제
아래에서 발생하여 변경할 수 없습니다. 또한 객체를 일시적으로 평평하게하고 싶지 않았습니다. 또한 주로 성능상의 이유와 직접 구현하는 재미 때문에 밑줄 / 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']));
// Results in...
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
// { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
// { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]
// same logic as above, but strong deviation for dynamic properties
function dynamicSort(properties) {
var sortOrder = 1;
// determine sort order by checking sign of last element of array
if(properties[properties.length - 1][0] === "-") {
sortOrder = -1;
// Chop off sign
properties[properties.length - 1] = properties[properties.length - 1].substr(1);
}
return function (a,b) {
propertyOfA = recurseObjProp(a, properties)
propertyOfB = recurseObjProp(b, properties)
var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
return result * sortOrder;
};
}
/**
* Takes an object and recurses down the tree to a target leaf and returns it value
* @param {Object} root - Object to be traversed.
* @param {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child']
* @param {Number} index - Must not be set, since it is implicit.
* @return {String|Number} The property, which is to be compared by sort.
*/
function recurseObjProp(root, leafs, index) {
index ? index : index = 0
var upper = root
// walk down one level
lower = upper[leafs[index]]
// Check if last leaf has been hit by having gone one step too far.
// If so, return result from last step.
if (!lower) {
return upper
}
// Else: recurse!
index++
// HINT: Bug was here, for not explicitly returning function
// https://stackoverflow.com/a/17528613/3580261
return recurseObjProp(lower, leafs, index)
}
/**
* Multi-sort your array by a set of properties
* @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child']
* @return {Number} Number - number for sort algorithm
*/
function dynamicMultiSort() {
var args = Array.prototype.slice.call(arguments); // slight deviation to base
return function (a, b) {
var i = 0, result = 0, numberOfProperties = args.length;
// REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature
// Consider: `.forEach()`
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(args[i])(a, b);
i++;
}
return result;
}
}
예
예를 들어 작업 JSBin에