I am working on an exercise that is based on the reduce exercise from underscore.js. Now, I have a solution that works but I believe it can be done better since I used a lot of copy pasting in my Frankenstein solution.
The Solution I found
This is the solution I have come up with:
_.reduce = function (collection, iteratee, accumulator, context) {
if (Array.isArray(collection)) {
var returnVal = accumulator !== undefined ? accumulator : collection[0];
if (accumulator !== undefined) {
for (var i = 0; i < collection.length; i++) {
returnVal = iteratee.call(
context,
returnVal,
collection[i],
i,
collection
);
}
} else {
for (var i = 1; i < collection.length; i++) {
returnVal = iteratee.call(
context,
returnVal,
collection[i],
i,
collection
);
}
}
console.log(returnVal);
return returnVal;
} else if (typeof collection === "object") {
var keys = Object.keys(collection);
var returnVal =
accumulator !== undefined ? accumulator : collection[keys[0]];
if (accumulator !== undefined) {
for (var i = 0; i < keys.length; i++) {
returnVal = iteratee.call(
context,
returnVal,
collection[keys[i]],
keys[i],
collection
);
}
} else {
for (var i = 1; i < keys.length; i++) {
returnVal = iteratee.call(
context,
returnVal,
collection[keys[i]],
keys[i],
collection
);
}
}
console.log(returnVal);
return returnVal;
}
};
As you can see, I distinguish between a collection that is an array, and a collection that is an object. This is my first conditional. Within this conditional I have another conditional for both the array and the object. This conditional checks whether accumulator is not undefined. If true, it runs the for loop from the first iteration, if false, it runs the for loop from the second iteration. I do this because when accumulator is undefined, it has to be the first value in the collection, and if I would then run the for loop from the first iteration, the first value would appear double.
What I have tried
I have tried adding a conditional inside the for loop to check if accumulator is undefined, if it was undefined I would continue. This however did not work because accumulator stays undefined obviously.
I also tried to add that conditional in the for loop and start the for loop from the second iteration, and the conditional would add the first value of the collection to returnVal manually (if accumulator is undefined). This also did not work because it messed up the results and gave it back in the wrong order.
What I am expecting
I don't know if it is possible, but I would like to shorten my code to make it more readable, and just better code in general. I think it is possible to shorten this code, I just can't see where and how. If there are any other improvements to be made, I would gladly hear about them to as it will help me become a better coder!!
Thanks in advance.
ps. I cannot use built-in functions like forEach(), map(), reduce() and filter().
Here a simplified code. It's used a single
forloop by setting the initial indexibased on whetheraccumulatorisundefinedor not. Ifaccumulatoris undefined, it starts from index1, skipping the first iteration. Ifaccumulatoris defined, it will start from index0, including the first iteration. And it's also better to useletinstead ofvar.