Menyortir (lebih banyak) Susunan Kompleks Objek
Karena Anda mungkin menemukan struktur data yang lebih kompleks seperti array ini, saya akan memperluas solusinya.
TL; DR
Adalah versi yang lebih pluggable berdasarkan jawaban yang sangat bagus dari @ ege-Özcan .
Masalah
Saya menemukan di bawah dan tidak bisa mengubahnya. Saya juga tidak ingin meratakan objek untuk sementara waktu. Saya juga tidak ingin menggunakan garis bawah / lodash, terutama karena alasan kinerja dan kesenangan untuk mengimplementasikannya sendiri.
var People = [
{Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
{Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
{Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
Tujuan
Tujuannya adalah untuk mengurutkannya berdasarkan People.Name.name
dan olehPeople.Name.surname
Rintangan
Sekarang, dalam solusi dasar menggunakan notasi braket untuk menghitung properti untuk mengurutkan secara dinamis. Namun, di sini, kita harus membuat notasi braket secara dinamis, karena Anda akan mengharapkannyaPeople['Name.name']
berfungsi - yang tidak.
Cukup melakukan People['Name']['name']
, di sisi lain, bersifat statis dan hanya memungkinkan Anda untuk turun n ke tingkat .
Larutan
Penambahan utama di sini adalah berjalan menyusuri objek pohon dan menentukan nilai daun terakhir, Anda harus menentukan, serta setiap daun perantara.
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;
}
}
Contoh
Contoh kerja di JSBin