最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

JavaScript reduce not working on an object - Stack Overflow

programmeradmin2浏览0评论

I am trying to understand how reduce works

var expense = [
    {
        item: "Bed",
        cost: 1499,
        date: "02-23-2018"
    },
    {
        item: "Phone",
        cost: 2499,
        date: "02-23-2018"
    },
    {
        item: "Book",
        cost: 400,
        date: "02-23-2018"
    },
    {
        item: "Mattress",
        cost: 700,
        date: "02-23-2018"
    },
    {
        item: "Food",
        cost: 300,
        date: "02-23-2018"
    }
];

var totalExpense = expense.reduce(function (a, b) {
    console.log(a.cost, b.cost);
    return a.cost + b.cost;
});

console.log(totalExpense);

this gives totalExpense as NaN.

Output:

1499 2499
undefined 400
undefined 700
undefined 300
NaN

When I perform the same operation with a simple expense array, it works fine.

I am trying to understand how reduce works

var expense = [
    {
        item: "Bed",
        cost: 1499,
        date: "02-23-2018"
    },
    {
        item: "Phone",
        cost: 2499,
        date: "02-23-2018"
    },
    {
        item: "Book",
        cost: 400,
        date: "02-23-2018"
    },
    {
        item: "Mattress",
        cost: 700,
        date: "02-23-2018"
    },
    {
        item: "Food",
        cost: 300,
        date: "02-23-2018"
    }
];

var totalExpense = expense.reduce(function (a, b) {
    console.log(a.cost, b.cost);
    return a.cost + b.cost;
});

console.log(totalExpense);

this gives totalExpense as NaN.

Output:

1499 2499
undefined 400
undefined 700
undefined 300
NaN

When I perform the same operation with a simple expense array, it works fine.

Share Improve this question edited Sep 27, 2021 at 5:46 Jun Yu 4241 gold badge8 silver badges22 bronze badges asked Jan 28, 2018 at 18:53 Stacy JStacy J 2,78116 gold badges59 silver badges93 bronze badges
Add a comment  | 

7 Answers 7

Reset to default 20

The first parameter you pass to reduce's callback is the previous value (a) - or the second argument you pass to reduce (the initial value)

[].reduce(function(a, b) { ... }, 0);
          ^ callback              ^ initial value

a will hold the result of each previous iteration, So to get the total of all costs, simply add b.cost

var expense = [{
    item: 'Bed',
    cost: 1499,
    date: '02-23-2018'
  },
  {
    item: 'Phone',
    cost: 2499,
    date: '02-23-2018'
  },
  {
    item: 'Book',
    cost: 400,
    date: '02-23-2018'
  },
  {
    item: 'Mattress',
    cost: 700,
    date: '02-23-2018'
  },
  {
    item: 'Food',
    cost: 300,
    date: '02-23-2018'
  }
];
var totalExpense = expense.reduce(function(a, b) {
  return a + b.cost;
}, 0);

console.log(totalExpense);

Using es6 syntax you could make it a one liner

var totalExpense = expense.reduce((a, {cost}) => a + cost, 0);

You need to provide an initial value which has a cost field in order to reference it in the accumulator. And you need to return that object:

expense.reduce(function(acc, curr){
    console.log(acc.cost, curr.cost);
    acc.cost += curr.cost;
    return acc;
    }, { cost: 0 });

Note the use of more meaningful variable names than a and b. This will make your code easier to understand. The Array.prototype.reduce callback should have an accumulator and current value. Name them as such to help yourself. The initial value provides an object with a cost field where you can write down your accumulated value.

Note that you could also just use a vanilla variable here if you wanted to. If you don't actually need an object:

var total = expense.reduce(function(acc, curr){
    acc += curr.cost;
    return acc;
    }, 0);
 console.log(total);
 >> 5398

You need to return whatever the next a should be. a.cost + b.cost is a number. It doesn’t have a cost property, so a.cost will be undefined after the first iteration.

Just provide a starting value 0. Also consider giving your parameters more appropriate names.

var totalExpense = expense.reduce(function(sum, item){
  return sum + item.cost;
}, 0);

You need an initial value. The reduce function takes the accumulated value as first parameter and the next element of the collection as second

var totalExpense = expense.reduce(function(accumulator, current) {
console.log({ accumulator: accumulator, currentCost: current.cost });
return accumulator + current.cost;
}, 0);

console.log({ totalExpense: totalExpense });

//total cost by reduce method

let totalExpense = expense.reduce((tem,val) => tem+=val.cost,0) console.log(totalExpense)

expense.reduce((sum, cur) => ({ cost: sum.cost + cur.cost })).cost;

Updated As @Viktor pointed, I didn't consider special case before.

function getTotelExpense(expense) {
    if (expense.length > 0 && expense[0].hasOwnProperty("cost"))
        return expense.reduce((sum, cur) => ({ cost: sum.cost + cur.cost })).cost;
    else return 0;
}

You can learn more in TypeError: Reduce of empty array with no initial value | MDN

Here's another way you can do it using the generic function foldMap – for more guidance on this beautiful function, I recommend this video.

const totalExpense =
  expense.foldMap (item => item.cost, 0)

console.log (totalExpense)
// 5398

For this, you'll need to define Array.prototype.foldMap and Number.prototype.concat – but this implementation and where it is defined is up to you

Array.prototype.foldMap = function (f, acc)
{
  return this.reduce ((acc, x, i) =>
    acc.concat (f (x, i, this)), acc)
}

Number.prototype.concat = function (m)
{
  return this + m
}

Here's a functioning code paste

Array.prototype.foldMap = function (f, acc)
{
  return this.reduce ((acc, x, i) =>
    acc.concat (f (x, i, this)), acc)
}

Number.prototype.concat = function (m)
{
  return this + m
}

const expense =
  [ { item: 'Bed'
    , cost: 1499
    , date: '02-23-2018'
    }
  , { item: 'Phone'
    , cost: 2499
    , date: '02-23-2018'
    }
  , { item: 'Book'
    , cost: 400
    , date: '02-23-2018'
    }
  , { item: 'Mattress'
    , cost: 700
    , date: '02-23-2018'
    }
  , { item: 'Food'
    , cost: 300
    , date: '02-23-2018'
    }
  ]
  
const totalExpense =
  expense.foldMap (item => item.cost, 0)

console.log(totalExpense)
// 5398

发布评论

评论列表(0)

  1. 暂无评论