Натуральная сортировка массива объектов по нескольким условиям
Имеем массив объектов:
const data = [
{"name": "John", "email": "[email protected]", "age": 36},
{"name": "Alex", "email": "[email protected]", "age": 18},
{"name": "Mari", "email": "[email protected]", "age": 18},
{"name": "John", "email": "[email protected]", "age": 19},
{"name": "Jane", "email": "[email protected]", "age": 25},
];
Массив условия для сортировки может состоять из разного количества элементов и в разной последовательности:
const condition = { "sort_by": [ "name", "age"]};
Мне нужно написать функцию, которая выполнит эту сортировку, причем при применение данных 2 условий мы сначала должны отсортировать по ключу name, а потом отсортированный массив еще отсортировать по ключу age, не теряя результата первой сортировки, т.е. после первого прохода получаем вот такой массив (сортировка по name):
[
{ name: 'Alex', email: '[email protected]', age: 18 },
{ name: 'Jane', email: '[email protected]', age: 25 },
{ name: 'John', email: '[email protected]', age: 36 },
{ name: 'John', email: '[email protected]', age: 19 },
{ name: 'Mari', email: '[email protected]', age: 18 }
]
конечный результат должен быть вот таким:
[
{ name: 'Alex', email: '[email protected]', age: 18 },
{ name: 'Jane', email: '[email protected]', age: 25 },
{ name: 'John', email: '[email protected]', age: 19 },
{ name: 'John', email: '[email protected]', age: 36 },
{ name: 'Mari', email: '[email protected]', age: 18 }
]
Мы меняем только 2 записи местами, 2-х John по возрасту, но остальная сортировка не меняется. Написал вот такой код:
const sortBy = (cond, arr) => {
const keys = cond.sort_by;
const inputArr = JSON.parse(JSON.stringify(arr))
let sortedArray;
keys.forEach(key => {
sortedArray = inputArr.sort((a, b) => {
return (typeof (a[key]) === 'number' && typeof (b[key]) === 'number')
? a[key] - b[key] : a[key].localeCompare(b[key])
})
})
return sortedArray
}
Но такой код делает сортировку 2 раза (сначала сортирует по name, а потом этот же массив сортирует по age и результат первой сортировки пропадает), и я получаю не тот результат что мне нужен. Подскажите как исправить эту проблему?
Если использовать такие условия сортировки:
sortedArray = inputArr.sort((a, b) => (a.name.localeCompare(b.name) || a.age - b.age))
то все работает как нужно, за исключением того, что я указываю хардкором ключи по которым сортирую, а они могут быть разные))
const data = [
{"name": "John", "email": "[email protected]", "age": 36},
{"name": "Alex", "email": "[email protected]", "age": 18},
{"name": "Mari", "email": "[email protected]", "age": 18},
{"name": "John", "email": "[email protected]", "age": 19},
{"name": "Jane", "email": "[email protected]", "age": 25},
];
const condition = { "sort_by": [ "name", "age"]};
const sortBy = (cond, arr) => {
const keys = cond.sort_by;
const inputArr = JSON.parse(JSON.stringify(arr))
let sortedArray;
keys.forEach(key => {
//sortedArray = inputArr.sort((a, b) => a[key].localeCompare(b[key]) || a[key] - b[key] )
//sortedArray = inputArr.sort((a, b) => (a.name.localeCompare(b.name) || a.age - b.age))
sortedArray = inputArr.sort((a, b) => {
//console.log(typeof (a[key]) === 'number' && typeof (b[key]) === 'number')
return (typeof (a[key]) === 'number' && typeof (b[key]) === 'number') ? a[key] - b[key] : a[key].localeCompare(b[key])
})
})
return sortedArray
}
console.log(sortBy(condition, data))
Ответы (1 шт):
Можете попробовать так:
const data = [
{"name": "John", "email": "[email protected]", "age": 36},
{"name": "Alex", "email": "[email protected]", "age": 18},
{"name": "Mari", "email": "[email protected]", "age": 18},
{"name": "John", "email": "[email protected]", "age": 19},
{"name": "Jane", "email": "[email protected]", "age": 25},
];
const compare = (a, b) => {
if (a === b) return 0;
if (a > b) return 1;
if (a < b) return -1;
}
const sortBy = (fields, arr) => {
return arr.sort((a, b) => {
for (field of fields) {
const result = compare(a[field], b[field]);
if (result === 0) continue;
return result;
}
return 0;
})
}
console.log(sortBy(["name", "age"], data));
console.log('---------------------------------------------------------')
console.log(sortBy(["name"], data));
console.log('---------------------------------------------------------')
console.log(sortBy(["email"], data));