Sıralama (daha fazla) Nesnelerin Karmaşık Dizileri
Muhtemelen bu dizi gibi daha karmaşık veri yapılarıyla karşılaştığınız için çözümü genişletirim.
TL; DR
@ Ege-Özcan'ın çok güzel cevabını temel alan daha geçmeli versiyonlardır .
Sorun
Aşağıdakilerle karşılaştım ve değiştiremedim. Ayrıca nesneyi geçici olarak düzleştirmek istemedim. Ben de alt çizgi / lodash kullanmak istemedim, temelde performans nedenleriyle ve bunu kendim uygulamak için eğlenceli.
var People = [
{Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
{Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
{Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
Hedef
Amaç, öncelikle People.Name.name
ve ikincil olarakPeople.Name.surname
Engeller
Şimdi, temel çözüm dinamik olarak sıralamak için özellikleri hesaplamak için köşeli ayraç gösterimi kullanır. Bununla birlikte, burada, braket gösterimini dinamik olarak da inşa etmek zorundayız, çünkü bazılarının People['Name.name']
işe yaramasını beklersiniz - ki bu işe yaramaz.
People['Name']['name']
Öte yandan, basitçe yapmak statiktir ve sadece n. Seviyeye inmenizi sağlar.
Çözüm
Buradaki ana ekleme, nesne ağacından aşağı inmek ve herhangi bir ara yaprağın yanı sıra belirtmeniz gereken son yaprağın değerini belirlemek olacaktır.
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;
}
}
Misal
JSBin üzerinde çalışma örneği