Каков альтернативный/лучший способ сопоставления значений ключа объекта без использования forEach
?
Это то, что у меня есть сейчас:
sortObject(source) {
const object = Object.assign({}, source);
Object.keys(object).forEach(key => {
// Sort array by priority (the higher the number, the higher the priority)
object[key] = object[key].sort((a, b) => b.priority - a.priority);
// Limit the array length to the 5
if (object[key].length > 5) {
object[key] = object[key].slice(0, 5);
}
});
return object;
}
source
- это объект, например:
{
base: [
{ id: 1, priority: 5 },
{ id: 2, priority: 10 },
{ id: 3, priority: 1 },
{ id: 4, priority: 5 },
{ id: 5, priority: 15 }
],
extra: [
{ id: 1, priority: 1 },
{ id: 2, priority: 5 },
{ id: 3, priority: 10 }
],
additional: [
{ id: 1, priority: 5 },
{ id: 2, priority: 10 },
{ id: 3, priority: 10 },
{ id: 4, priority: 15 },
{ id: 5, priority: 1 },
{ id: 6, priority: 29 },
{ id: 7, priority: 100 },
{ id: 8, priority: 100 },
{ id: 9, priority: 5 }
]
}
Конечный результат выглядит так:
{
base: [
{ id: 5, priority: 15 },
{ id: 2, priority: 10 },
{ id: 1, priority: 5 },
{ id: 4, priority: 5 },
{ id: 3, priority: 1 }
],
extra: [
{ id: 3, priority: 10 },
{ id: 2, priority: 5 },
{ id: 1, priority: 1 }
],
additional: [
{ id: 7, priority: 100 },
{ id: 8, priority: 100 },
{ id: 6, priority: 29 },
{ id: 4, priority: 15 },
{ id: 2, priority: 10 }
]
}
есть ли лучший/более чистый способ сделать это?
Я бы посмотрел на Object.entries
(новый как на ES2017, но полиполняемый) и разрушил в цикле for-of
loop.
Если ничто иное не имеет доступа к массивам на source
(что я, как правило, предполагаю, поскольку sort
работает на месте, поэтому код уже изменяет исходный массив, но в то же время source
поступает извне, поэтому... ):
sortObject(source) {
const object = Object.assign({}, source);
for (const [key, array] of Object.entries(object)) {
array.sort((a, b) => b.priority - a.priority);
array.length = Math.min(array.length, 5);
}
return object;
}
Если что-то еще имеет доступ к этим массивам, и вы не должны изменять их, кроме их сортировки, тогда вам понадобится ваша первоначальная проверка length
и slice
:
sortObject(source) {
const object = Object.assign({}, source);
for (const [key, array] of Object.entries(object)) {
array.sort((a, b) => b.priority - a.priority);
if (array.length > 5) {
object[key] = array.slice(0, 5);
}
}
return object;
}
Ваш код подсказывает, что вы, возможно, не реализовали работу sort
на месте, поскольку вы возвращали результат обратно в исходное местоположение. Если это так, и вы не собирались сортировать массивы на месте, вам нужно будет скопировать массивы перед сортировкой:
sortObject(source) {
const object = Object.assign({}, source);
for (const [key, array] of Object.entries(object)) {
object[key] = array = array.slice();
array.sort((a, b) => b.priority - a.priority);
array.length = Math.min(array.length, 5);
}
return object;
}
Вы можете заменить
object[key] = array = array.slice();
array.sort((a, b) => b.priority - a.priority);
с
object[key] = array = Array.from(array).sort((a, b) => b.priority - a.priority);
если вам нравится, но это будет использовать итератор, что больше накладных расходов, чем slice
.
Вы также можете использовать карту для циклизации записей объекта и сращивания для отсечения длины массива:
const getSortedObj = (source) => {
let obj = Object.assign({}, source);
Object.entries(obj).map( entry => {
let [key, arr] = entry;
arr.sort((a, b) => b.priority - a.priority).splice(Math.min(arr.length, 5));
return entry;
});
return obj;
};
map
. map
строит и возвращает массив. Если вы не используете возвращаемое значение map
(массив, который она создает) и не хотите использовать for-of
, используйте forEach
.