Reputation: 6556
What is the alternative/best way to map through an object key-values without using forEach
?
This is what I have currently:
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
is an object like:
{
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 }
]
}
The final output is like:
{
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 }
]
}
is there a better/cleaner way to do this?
Upvotes: 1
Views: 2984
Reputation: 323
You can also use map for looping the object entries and splice for cutting off the array length:
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;
};
Upvotes: 0
Reputation: 1074335
I'd look at Object.entries
(new as of ES2017 but polyfillable) and destructuring in a for-of
loop.
If nothing else has access to the arrays on source
(which I tend to assume, since sort
works in-place, so the code already modifies the original array; but at the same time, source
is coming in from outside, so...):
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;
}
If something else has access to those arrays and you shouldn't modify them other than sorting them, then you'll need your original length
check and 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;
}
Your code suggests you may not have realized sort
works in-place since you were assigning the result back to the original location. If so and you didn't intend to sort the arrays in-place, you'll need to copy the arrays before sorting:
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;
}
You could replace
object[key] = array = array.slice();
array.sort((a, b) => b.priority - a.priority);
with
object[key] = array = Array.from(array).sort((a, b) => b.priority - a.priority);
if you like, but that'll use an iterator, which is more overhead than slice
.
Upvotes: 3