Could you please suggest any shorter code to solve following problem. I have array of objects:
const arr1=[
{ '1': { grade: 1.3, counter: 2 } },
{ '1': { grade: 2.8, counter: 2 } },
{ '2': { grade: 4.5, counter: 1 } },
{ '2': { grade: 2.4, counter: 1 } }
]
the output should look like:
const obj1={
'1': {grade:4.1,counter:4}
'2': {grade:6.9,counter:2}
}
here is the code i have tried :
arr1.reduce((acc,e)=> {
let element = Object.keys(e)
if(!acc.hasOwnProperty(element)){
acc[element]={grade:0,counter:0}
}
acc[element].grade+= e[element].grade
acc[element].counter+= e[element].counter
return acc
}, {})
Thank you
Your problem here is that Object.keys(e) return an array of keys and not a single key.
If your object will always be the same (with one key) the you can get the key with : let element = Object.keys(e)[0]
I've decomposed the code with 2 main parts.
Getting the key of the current item (with const key = Object.keys(current)[0])
Checking if the newObject has the key
If yes : updating the grade and counter value with the current object
If no : adding the current object to the key
const arr1 = [{
'1': {
grade: 1.3,
counter: 2
}
},
{
'1': {
grade: 2.8,
counter: 2
}
},
{
'2': {
grade: 4.5,
counter: 1
}
},
{
'2': {
grade: 2.4,
counter: 1
}
}
]
const newObject = arr1.reduce((newObject, current) => {
const key = Object.keys(current)[0]
const associatedObject = newObject[key]
if (associatedObject) {
associatedObject.grade += current[key].grade
associatedObject.counter += current[key].counter
} else {
newObject[key] = current[key]
}
return newObject
}, {})
console.log(newObject)
I would go for:
arr1.reduce((o,n)=>{
Object.keys(n).forEach((key)=>{
if(!o[key]) o[key]={grade:0, counter:0};
o[key]["grade"] += n[key]["grade"];
o[key]["counter"] += n[key]["counter"];
});
return o;
},{});
Step1: reducing over the array, acc = {}
Step2: iterating over every key of the object at the current index
Step3: summing up the according properties
You forgot to iterate over the keys.
Comment: As a pons asinorum I use for array.reduce() the variable names:
o meaning old value (=acc=_accumulator)
n meaning new value.
Try this
let arr1=[{'1': {grade: 1.3, counter: 2}},{'1': {grade: 2.8, counter: 2}},{'2': {grade: 4.5, counter: 1}},{'2': {grade: 2.4, counter: 1}}];
arr1 = arr1.reduce((acc, obj) => {
let [k, v] = Object.entries(obj)[0];
if(!acc.hasOwnProperty(k)) acc[k] = {grade:0,counter:0};
acc[k].grade += v.grade;
acc[k].counter += v.counter;
return acc
}, {});
console.log(arr1)
Object.keys returns an array of strings, so to check here you would probably want the first one:
arr1.reduce((acc, e) => {
const element = Object.keys(e)[0]; // `[0]` accesses the first key
if(!acc.hasOwnProperty(element)){
acc[element]={grade:0,counter:0}
}
acc[element].grade+= e[element].grade
acc[element].counter+= e[element].counter
return acc
}, {});
Then instead of the if statement you can use the new logical nullish assignment operator:
arr1.reduce((acc, e) => {
const element = Object.keys(e)[0];
acc[element] ??= { grade: 0, counter: 0 };
acc[element].grade += e[element].grade;
acc[element].counter += e[element].counter;
return acc
}, {});
This is probably as short as I'd go before it starts getting pointless.
Even further; using nullish coalescing and optional chaining:
arr1.reduce((acc, e) => {
const element = Object.keys(e)[0];
acc[element] = {
grade: (acc[element]?.grade ?? 0) + e[element].grade,
counter: (acc[element?.counter ?? 0) + e[element].counter,
};
return acc
}, {});
With Object.assign to do it all in one line:
arr1.reduce((acc, e) => {
const element = Object.keys(e)[0];
return Object.assign(acc, {
[element]: {
grade: (acc[element]?.grade ?? 0) + e[element].grade,
counter: (acc[element?.counter ?? 0) + e[element].counter,
},
});
}, {});
Finally, just for kicks, let's inline the element variable altogether to get this amazing line:
arr1.reduce((acc, e) => Object.assign(acc, {
[Object.keys(e)[0]]: {
grade: (acc[Object.keys(e)[0]]?.grade ?? 0) + e[Object.keys(e)[0]].grade,
counter: (acc[Object.keys(e)[0]]?.counter ?? 0) + e[Object.keys(e)[0]].counter,
},
}), {});
Another solution is:
const obj1 = arr1.reduce((acc, value) => {
if(acc[Object.keys(value)[0]]) {
acc[Object.keys(value)[0]].grade = acc[Object.keys(value)[0]].grade + value[Object.keys(value)[0]].grade;
acc[Object.keys(value)[0]].counter = acc[Object.keys(value)[0]].counter + value[Object.keys(value)[0]].counter;
} else {
acc[Object.keys(value)[0]] = value[Object.keys(value)[0]];
}
return acc;
})
Related
I am trying to get the sum of all (a) properties and console.log says NAN
const numbers = [{ a: 1 }, { a: 6 }, { a: 3 }, { d: 4 }, { e: 5 }, { f: 5 }];
const filterNumbers = numbers.reduce((currenttotal, item) => {
return item.a + currenttotal;
}, 0);
console.log(filterNumbers);
is there something wrong?
trying to get the sum of only a keys
Hate to be the person that takes someone's comment and makes an answer out of it, but as #dandavis has suggested, you need to, in someway, default to a value if the 'a' key doensn't exist.
This can be done in a variety of ways:
Short circuit evaluation:
const filterNumbers = numbers.reduce((currenttotal, item) => {
return (item.a || 0) + currenttotal;
}, 0);
The in operator:
const filterNumbers = numbers.reduce((currenttotal, item) => {
return ("a" in item ? item.a : 0) + currenttotal;
}, 0);
Nullish coalescing operator:
const filterNumbers = numbers.reduce((currenttotal, item) => {
return (item.a ?? 0) + currenttotal;
}, 0);
Checking for falsey values of item.a (basically longer short circuit evaluation):
const filterNumbers = numbers.reduce((currenttotal, item) => {
return (item.a ? item.a : 0) + currenttotal;
}, 0);
Since not all fields have an a key the reduce does not find a value and return NAN.
The solution it`s the same as the previous answer, but i rather use immutability in variables since prevents future erros.
const numbers = [{ a: 1 }, { a: 6 }, { a: 3 }, { d: 4 }, { e: 5 }, { f: 5 }];
const filterNumbers = numbers.reduce((currenttotal, item) => {
const keys = Object.keys(item);
return item[keys[0]] + currenttotal;
}, 0);
console.log(filterNumbers);
and in the case u need to sum only with the specific key:
const filterNumbers = numbers.reduce((currenttotal, item) => {
return (item.a ?? 0) + currenttotal;
}, 0);
console.log(filterNumbers);
Not all elements have an a key. If you want to dynamically get whichever key is present, this should work:
const numbers = [{ a: 1 }, { a: 6 }, { a: 3 }, { d: 4 }, { e: 5 }, { f: 5 }];
const filterNumbers = numbers.reduce((currenttotal, item) => {
let keys = Object.keys(item);
return item[keys[0]] + currenttotal;
}, 0);
console.log(filterNumbers);
This question already has answers here:
Sort Array Elements (string with numbers), natural sort
(8 answers)
Closed 11 months ago.
I am trying to arrange given values in ascending orders
const value = [
{ val: "11-1" },
{ val: "12-1b" },
{ val: "12-1a" },
{ val: "12-700" },
{ val: "12-7" },
{ val: "12-8" },
];
I am using code below to sort this in ascending order:
value.sort((a,b)=>(a.val >b.val)? 1:((b.val>a.val)?-1:0));
The result of this sort is in the order 11-1,12-1a, 12-1b, 12-7, 12-700, 12-8. However, I want the order to be 11-1,12-1a, 12-1b, 12-7, 12-8, 12-700.
How can I achieve that?
If you're only interested of sorting by the value after the hyphen you can achieve it with this code:
const value = [
{val:'12-1'},
{val:'12-700'},
{val:'12-7'},
{val:'12-8'},
];
const sorted = value.sort((a,b) => {
const anum = parseInt(a.val.split('-')[1]);
const bnum = parseInt(b.val.split('-')[1]);
return anum - bnum;
});
console.log(sorted);
updated the answer as your question update here's the solution for this:
const value = [{ val: '11-1' }, { val: '12-1b' }, { val: '12-1a' }, { val: '12-700' }, { val: '12-7' }, { val: '12-8' }];
const sortAlphaNum = (a, b) => a.val.localeCompare(b.val, 'en', { numeric: true });
console.log(value.sort(sortAlphaNum));
You can check the length first and then do the sorting as follow:
const value = [
{ val: "12-1" },
{ val: "12-700" },
{ val: "12-7" },
{ val: "12-8" },
];
const result = value.sort(
(a, b)=> {
if (a.val.length > b.val.length) {
return 1;
}
if (a.val.length < b.val.length) {
return -1;
}
return (a.val >b.val) ? 1 : ((b.val > a.val) ? -1 : 0)
}
);
console.log(result);
little change's to #Christian answer it will sort before and after - value
const value = [{ val: '12-1' }, { val: '12-700' }, { val: '11-7' }, { val: '12-8' }];
const sorted = value.sort((a, b) => {
const anum = parseInt(a.val.replace('-', '.'));
const bnum = parseInt(b.val.replace('-', '.'));
return anum - bnum;
});
console.log(sorted);
If you want to check for different values both before and after the hyphen and include checking for letters, the solution at the end will solve this.
Here's what I did:
Created a regex to split the characters by type:
var regexValueSplit = /(\d+)([a-z]+)?-(\d+)([a-z]+)?/gi;
Created a comparison function to take numbers and letters into account:
function compareTypes(alpha, bravo) {
if (!isNaN(alpha) && !isNaN(bravo)) {
return parseInt(alpha) - parseInt(bravo);
}
return alpha > bravo;
}
Split the values based on regexValueSplit:
value.sort((a, b) => {
let valuesA = a.val.split(regexValueSplit);
let valuesB = b.val.split(regexValueSplit);
This produces results as follows (example string "12-1a"):
[
"",
"12",
null,
"1",
"a",
""
]
Then, since all the split arrays should have the same length, compare each value in a for loop:
for (let i = 0; i < valuesA.length; i++) {
if (valuesA[i] !== valuesB[i]) {
return compareTypes(valuesA[i], valuesB[i]);
}
}
// Return 0 if all values are equal
return 0;
const value = [{
val: "11-1"
},
{
val: "12-1b"
},
{
val: "12-1a"
},
{
val: "12-700"
},
{
val: "12-7"
},
{
val: "12-8"
},
];
var regexValueSplit = /(\d+)([a-z]+)?-(\d+)([a-z]+)?/gi;
function compareTypes(alpha, bravo) {
if (!isNaN(alpha) && !isNaN(bravo)) {
return parseInt(alpha) - parseInt(bravo);
}
return alpha > bravo;
}
value.sort((a, b) => {
let valuesA = a.val.split(regexValueSplit);
let valuesB = b.val.split(regexValueSplit);
for (let i = 0; i < valuesA.length; i++) {
if (valuesA[i] !== valuesB[i]) {
return compareTypes(valuesA[i], valuesB[i]);
}
}
return 0;
});
console.log(JSON.stringify(value, null, 2));
Since you are sorting on string values, try using String.localeCompare for the sorting.
Try sorting on both numeric components of the string.
const arr = [
{val:'12-1'},
{val:'11-900'},
{val:'12-700'},
{val:'12-7'},
{val:'11-1'},
{val:'12-8'},
{val:'11-90'},
];
const sorter = (a, b) => {
const [a1, a2, b1, b2] = (a.val.split(`-`)
.concat(b.val.split(`-`))).map(Number);
return a1 - b1 || a2 - b2; };
console.log(`Unsorted values:\n${
JSON.stringify(arr.map(v => v.val))}`);
console.log(`Sorted values:\n${
JSON.stringify(arr.sort(sorter).map(v => v.val))}`);
I have an array of objects and I want to add an element to specific index when a certain attribute changes compared to the previous one.
We have:
const arr = [
{ num: 1 },
{ num: 1 },
{ num: 1 },
{ num: 3 },
{ num: 3 },
{ num: 4 },
{ num: 5 },
];
I want it to become
const arr = [
{ separator:true }
{ num: 1 },
{ num: 1 },
{ num: 1 },
{ separator:true }
{ num: 3 },
{ num: 3 },
{ separator:true }
{ num: 4 },
{ separator:true }
{ num: 5 },
];
I did this:
const getIndexes = (myArr) => {
let indexes = [];
let previousValue = null;
myArr.forEach((el, idx) => {
if (el.num !== previousValue) {
indexes.push(idx);
previousValue = el.num;
}
});
return indexes;
};
const insertSeparator = (arr) => {
let result = arr;
getIndexes(arr).forEach((position) => result.splice(position, 0, { separator: true }));
return result
};
and it returns:
[
{ separator: true },
{ num: 1 },
{ num: 1 },
{ separator: true },
{ num: 1 },
{ separator: true },
{ separator: true },
{ num: 3 },
{ num: 3 },
{ num: 4 },
{ num: 5 }
]
Maybe because of the "new" size of the array, because it is getting bigger and changes its dimension.
What do you think is the best way to solve this?
Run it through .flatMap()
const result = arr.flatMap((obj, idx, arr) => {...
.flatMap() is .map() and .flat() combined, so it transforms the contents of a copy of the given array and removes the brackets []. Next, we return the first object with a separator:
if (idx == 0) {
// returns are wrapped in brackets because they'll be removed before being returned
return [{separator: true}, obj];
}
The next step is to compare the current value with the previous value:
obj.num == arr[idx - 1].num ? // current value vs previous value
[arr[idx - 1]] : // if they are the same value return previous value
[{separator: true}, obj]; /* if they are not the same then return that separator
and current */
const arr = [
{ num: 1 },
{ num: 1 },
{ num: 1 },
{ num: 3 },
{ num: 3 },
{ num: 4 },
{ num: 5 },
];
const result = arr.flatMap((obj, idx, arr) => {
if (idx == 0) {
return [{
separator: true
}, obj];
}
return obj.num == arr[idx - 1].num ? [arr[idx - 1]] : [{
separator: true
}, obj];
});
console.log(JSON.stringify(result, null, 2));
I propose this solution which would consume only one iteration with a reduce :
const arr = [{
num: 1
},
{
num: 1
},
{
num: 1
},
{
num: 3
},
{
num: 3
},
{
num: 4
},
{
num: 5
},
];
let prev_value = arr[0];
const result = arr.reduce((acc, val) => {
const insert = (val.num !== prev_value.num) ? [{
separator: true
}, val] : [val];
prev_value = val;
return acc.concat(insert)
}, [{
separator: true
}, ])
console.log(result)
There must be other ways to do it too. But with a simple modification to your code it can be done. You just need to keep track of the offset with a new variable, incrementing it in the loop:
const arr = [
{ num: 1 },
{ num: 1 },
{ num: 1 },
{ num: 3 },
{ num: 3 },
{ num: 4 },
{ num: 5 },
];
const getIndexes = (myArr) => {
let indexes = [];
let previousValue = null;
myArr.forEach((el, idx) => {
if (el.num !== previousValue) {
indexes.push(idx);
previousValue = el.num;
}
});
return indexes;
};
const insertSeparator = (arr) => {
let result = [...arr];
let offset = -1;
getIndexes(arr).forEach((position) => {
offset++;
return result.splice(position+offset, 0, { separator: true });
});
return result
};
console.log(insertSeparator(arr));
Note: If you want to start with 0 you can do the increment in the .splice() itself : result.splice(position+(offset++),
const positions = [];
//arr.sort((a, b) => a.num - b.num); You can uncomment this line to ensure that the array will always sorted based on num property
arr.forEach((item, index) => {
if (index < arr.length - 1 && item.num != arr[index + 1].num) {
positions.push(index + 1);
}
});
let counter = 0;
positions.forEach((pos) => {
arr.splice(pos + counter++, 0, { separator: true });
});
console.log(arr);
You want to:
Do something which each item in a list
Want to return something other than a list of the same size.
Then I would suggest the good all-round Array.prototype.reduce() function.
const separator = {separator: true};
arr.reduce((result, item) => {
if (result.at(-1)?.num === item.num) {
return [...result, separator, item];
}
return [...result, item]
}, [])
This is (according to me) easier, cleaner and safer since it doesn't mutate variables.
Note
Array.prototype.at() is at the time of writing a new function. If you are using an ancient browser that doesn't support it you can use arr[arr.length -1] to get the last item instead.
I have a function called tree, which takes array of objects (as data fields from a database) and array of strings for keys. The function loops through rowsArray and recursively creates object with nested properties based on keyArray.
const tree = (rowsArray, keysArray) => {
return rows.reduce((acc, row) => {
const groupBy = (row, keys,) => {
const [first, ...rest] = keys;
if (!first) return [row];
return {
[row[first]]: groupBy(row, rest),
}
};
acc = {...groupBy(row, keys), ...acc};
return acc;
}, {});
}
The data is following:
const data = [{
ID: 1,
Main: "Financial",
Sub: "Forecasts",
Detail: "General"
}, {
ID: 2,
Main: "Financial",
Sub: "HR",
Detail: "Headcount"
}];
const result1 = tree(data, ["Main", "Sub", "Detail"]);
console.log(result1);
When I log the result, I get:
/*
// actual output
{
Financial: {
Forecasts: {
General: [Array]
}
}
}
Whereas, I would like to get following:
// expected
{
Financial: {
Forecasts: {
General: [Array]
},
HR: {
Headcount: [Array]
}
}
}
*/
The problem is, that acc variable in main function gets overridden and I get new object, instead of accumulative and I am not quite sure how to recursively build this object. I tried to pass instances of acc to groupBy function (to remember previous results), but no luck.
Do you have any idea how I could rewrite tree function or groupBy function to accomplish my goal? Thanks!
You could do it like this:
function tree(rows, keys) {
return rows.reduce( (acc, row) => {
keys.reduce( (parent, key, i) =>
parent[row[key]] = parent[row[key]] || (i === keys.length - 1 ? [row] : {})
, acc);
return acc;
}, {});
}
const data = [{ID: 1,Main: "Financial",Sub: "Forecasts",Detail: "General"}, {ID: 2,Main: "Financial",Sub: "HR", Detail: "Headcount" }];
const result1 = tree(data, ["Main", "Sub", "Detail"]);
console.log(result1);
Be aware that the spread syntax makes a shallow copy. Instead, in this solution, the accumulator is passed to the inner reduce. And so we actually merge the new row's hierarchical data into the accumulator on-the-spot.
The problem is your merge function is not deep. When you assign the values to the accumulator you overwrite existing properties - in this case Financial.
I included a deep merge function from here and now it works.
I also fixed some reference errors you had:
rows => rowsArray
keys = keysArray
// deep merge function
function merge(current, update) {
Object.keys(update).forEach(function(key) {
// if update[key] exist, and it's not a string or array,
// we go in one level deeper
if (current.hasOwnProperty(key) &&
typeof current[key] === 'object' &&
!(current[key] instanceof Array)) {
merge(current[key], update[key]);
// if update[key] doesn't exist in current, or it's a string
// or array, then assign/overwrite current[key] to update[key]
} else {
current[key] = update[key];
}
});
return current;
}
const tree = (rowsArray, keysArray) => {
return rowsArray.reduce((acc, row) => {
const groupBy = (row, keys, ) => {
const [first, ...rest] = keys;
if (!first) return [row];
return {
[row[first]]: groupBy(row, rest),
}
};
acc = merge(groupBy(row, keysArray), acc);
return acc;
}, {});
}
const data = [{
ID: 1,
Main: "Financial",
Sub: "Forecasts",
Detail: "General"
}, {
ID: 2,
Main: "Financial",
Sub: "HR",
Detail: "Headcount"
}];
const result1 = tree(data, ["Main", "Sub", "Detail"]);
console.log(result1);
You could iterate the keys and take either an object for not the last key or an array for the last key and push then the data to the array.
const tree = (rowsArray, keysArray) => {
return rowsArray.reduce((acc, row) => {
keysArray
.map(k => row[k])
.reduce((o, k, i, { length }) => o[k] = o[k] || (i + 1 === length ? []: {}), acc)
.push(row);
return acc;
}, {});
}
const data = [{ ID: 1, Main: "Financial", Sub: "Forecasts", Detail: "General" }, { ID: 2, Main: "Financial", Sub: "HR", Detail: "Headcount" }];
const result1 = tree(data, ["Main", "Sub", "Detail"]);
console.log(result1);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can iterate over the data and created a unique key based on the keys provided and then recursively generate the output structure by deep cloning.
const data = [{
ID: 1,
Main: "Financial",
Sub: "Forecasts",
Detail: "General"
}, {
ID: 2,
Main: "Financial",
Sub: "HR",
Detail: "Headcount"
}];
function generateKey(keys,json){
return keys.reduce(function(o,i){
o += json[i] + "_";
return o;
},'');
}
function merge(first,second){
for(var i in second){
if(!first.hasOwnProperty(i)){
first[i] = second[i];
}else{
first[i] = merge(first[i],second[i]);
}
}
return first;
}
function generateTree(input,keys){
let values = input.reduce(function(o,i){
var key = generateKey(keys,i);
if(!o.hasOwnProperty(key)){
o[key] = [];
}
o[key].push(i);
return o;
},{});
return Object.keys(values).reduce(function(o,i){
var valueKeys = i.split('_');
var oo = {};
for(var index = valueKeys.length -2; index >=0 ;index--){
var out = {};
if(index === valueKeys.length -2){
out[valueKeys[index]] = values[i];
}else{
out[valueKeys[index]] = oo;
}
oo = out;
}
o = merge(o,oo);
return o;
},{});
}
console.log(generateTree(data,["Main", "Sub", "Detail"]));
jsFiddle Demo - https://jsfiddle.net/6jots8Lc/
I'm saving an object in state that looks like:
ingredients: {
salad: {
amount: 3,
basePrice: 1
},
cheese: {
amount: 2,
basePrice: 1.2
}
}
I want to use this in my component's state as follows
ingredients: {
salad: 3,
cheese: 2
}
I used Object.keys and map at first but it returns an Array of key value pairs instead of objects.
Although this works:
const newIngredientsObject = {};
for (const i in ingredientsObject)
newIngredientsObject[i] = ingredientsObject[i].amount;
return newIngredientsObject;
I want to find a solution without a helper method, as such:
const mapStateToProps = state => {
return {
ingredients: Object.keys(state.burger.ingredients).map(i => (
{ [i]: state.burger.ingredients[i].amount } )),
totalPrice: state.burger.totalPrice
}
};
You could map the entries of the object by using the amount property of the values and take Object.assign for getting a new object.
var ingredients = { salad: { amount: 3, basePrice: 1 }, cheese: { amount: 2, basePrice: 1.2 } },
result = Object.assign(
...Object.entries(ingredients).map(([key, value]) => ({ [key]: value.amount }))
);
console.log(result);
when you want to create one object to inside to another go this web
object 1 = {
content 1 = {
stuff = {
},
more Stuff = {
}
}
}
object 2 = {
key 1:"",
key 2:""
}
object 1.content 1 = object 2;
You asked a solution with Object.keys, here is one:
var x = {ingredients: {
salad: {
amount: 3,
basePrice: 1
},
cheese: {
amount: 2,
basePrice: 1.2
}
}}
Object.keys(x.ingredients).map((d,i)=>[d,x.ingredients[d].amount]).reduce((ac,d,i)=>(ac[d[0]]=d[1],ac),{})
//{salad: 3, cheese: 2}
The shortest I could come up with it using Object.keys and reduce
const ingredients = {
salad: {
amount: 3,
basePrice: 1
},
cheese: {
amount: 2,
basePrice: 1.2
}
};
let newObject = Object.keys(ingredients).reduce((acc, val) => {
acc[val] = ingredients[val].amount;
return acc;
}, {});
console.log(newObject);
ANSWER:
Thanks for the solutions provided by #ibowankenobi and #Nina Scholz
Reduce function:
Object.keys(ingredients)
.map( (d, i) => [d, ingredients[d].amount])
.reduce( (ac, d, i) => (ac[d[0]] = d[1], ac), {} );
Entries function:
Object.assign(...Object.entries(ingredients)
.map( ([key, value]) => ({ [key]: value.amount }) ) );
reduce: 0.0849609375ms
entries: 0.1650390625ms
forLoop: 0.07421875ms
reduce: 0.024169921875ms
entries: 0.048095703125ms
forLoop: 0.010009765625ms
reduce: 0.010009765625ms
entries: 0.016845703125ms
forLoop: 0.0078125ms
After some testing, it seems like using a for loop is the most efficient and after that the reduce function.