1

I spent hours trying to debug a particular code, at the very end i noticed something i don't understand with arr reduce function. Take the below code example

var arr = [{
  start: 1,
  value: 4
}, {
  start: 2,
  value: 5
}, {
  start: 3,
  value: 1
}, {
  start: 4,
  value: 41
}, {
  start: 5,
  value: 14
}, {
  start: 6,
  value: 3
}];

const getMinValue = function(a, b) {
  return (a.value < b.value) ? a.start : b.start;
}

console.log('The min value ', arr.reduce(getMinValue));

The console above returns 6.However, from, the array , its noticeable that the value is minimum at start:3. Rewriting the code to below however,

var arr = [{
  start: 1,
  value: 4
}, {
  start: 2,
  value: 5
}, {
  start: 3,
  value: 1
}, {
  start: 4,
  value: 41
}, {
  start: 5,
  value: 14
}, {
  start: 6,
  value: 3
}];

const getMinValue = function(a, b) {
  return (a.value < b.value) ? a : b;
}

console.log('The min value ', arr.reduce(getMinValue));

returns object {start: 3, value: 1} which is exactly correct. Hence

console.log('The min value ', arr.reduce(getMinValue).start);

is correct. Why does the first one differ pls ? Why does it return 6 ? . Is there something i am mistaking about reduce or my getMin function ? Any help would be appreciated.

sabithpocker
  • 15,274
  • 1
  • 42
  • 75
Nuru Salihu
  • 4,756
  • 17
  • 65
  • 116
  • 1
    You are returning a number in reduce to be `a` on the next iteration. Numbers don't have `value` or `start` properties. – Paul Jan 30 '18 at 05:58
  • 1
    Your reduce function becomes `return (undefined < undefined ? undefined : b.start`, so you just always return `b.start` and end up returning the start value of the final object in your array at the end. – Paul Jan 30 '18 at 06:00
  • @Paulpro oh oh oh oic . My comparison in dependent on the return previous value ? OMG , totally overlooked this. Thank you. – Nuru Salihu Jan 30 '18 at 06:01

3 Answers3

2

Why does it return 6 ?

because a is an accumulator which also happens to be return value of every iteration.

This line

return (a.value < b.value) ? a.start : b.start;

translates to conditional expression as

{start: 1, value : 4}.value < { start: 2, value: 5}.value

and next time onwards

(4).value < { start: 3,  value: 1 } //false hence return 1

Since (4).value is undefined and comparison with undefined always returns false.

Last iteration will be

(14).value < { start: 6,  value: 3 } 

return 6.

gurvinder372
  • 66,980
  • 10
  • 72
  • 94
2

Because whatever you return from the function you pass into reduce becomes the NEXT value of a.

const someReducer = (accumulator, x) => {
  // whatever I return here is the new value of the accumulator
  return accumulator.value < x.value ? accumulator.start : x.start;
}

someArray.reduce(someReducer);

The value of accumulator on the first time around is an object just like value. Then you return a number. On the second time around, accumulator is now the number you returned.

In general, you should also be using the second argument of reduce, which is the initial value of the reducer. This is incredibly important if you have situations where your ideal accumulator type is different than the type of values in your array.

In the case where you have a slightly simpler version you might consider:

values.reduce(getMinValue, Infinity);

Your initial function would work fine, if it were changed to

const getMinValue = (accumulator, x) =>
  accumulator < x.value ? accumulator : x.value;

In this example, accumulator is always a number, and x is one of your objects. This isn't quite what you asked for in the original question, but

.reduce(getMinValue, { start: 0, value: Infinity })

would also work.

Norguard
  • 26,167
  • 5
  • 41
  • 49
0

The filter() method returns a new array created from all elements that pass a certain test preformed on an original array.

var landSum = data.reduce(function(sum, d) {
  return sum + d.land_area;
}, 0);
console.log(landSum);

The first parameter to reduce is the callback function that will return the running "total" of the reduction. This function is passed in the previous value returned from the last time the callback was called. Here, that parameter - sum provides the running total as we move through the array. The second parameter to the callback d is the current value of the array we are working on.

reduce can take an initial value, which is the second parameter to the reduce call. For this example, we start the sum at 0. If there is no starting value provided, then for the first execution of the callback (when there is no previous value) the first parameter to the callback will be the value of the first element of the array, and the reduction starts with the second element.

So in you case you are passing the variable as return to the reduce that is why the above results are obtained

deepak thomas
  • 1,118
  • 9
  • 23