JavaScript 减少不在对象上工作
JavaScript reduce not working on an object
我正在尝试了解 reduce 的工作原理
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);
这给出 totalExpense 为 NaN
。
输出:
1499 2499
undefined 400
undefined 700
undefined 300
NaN
当我用一个简单的费用数组执行相同的操作时,它工作正常。
这是使用通用函数 foldMap
实现的另一种方法 – 有关此漂亮函数的更多指导,我推荐 this video。
const totalExpense =
expense.foldMap (item => item.cost, 0)
console.log (totalExpense)
// 5398
为此,您需要定义 Array.prototype.foldMap
和 Number.prototype.concat
– 但此实现及其定义位置由您决定
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
}
这是一个有效的代码粘贴
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
您需要提供一个包含 cost
字段的初始值,以便在累加器中引用它。您需要 return 该对象:
expense.reduce(function(acc, curr){
console.log(acc.cost, curr.cost);
acc.cost += curr.cost;
return acc;
}, { cost: 0 });
注意使用比 a
和 b
更有意义的变量名。这将使您的代码更易于理解。 Array.prototype.reduce
回调应该有一个累加器和当前值。这样命名它们以帮助您自己。初始值提供了一个带有 cost
字段的对象,您可以在其中记下您的累计值。
请注意,如果您愿意,也可以在此处使用普通变量。如果您实际上不需要对象:
var total = expense.reduce(function(acc, curr){
acc += curr.cost;
return acc;
}, 0);
console.log(total);
>> 5398
您传递给 reduce 的回调的第一个参数是先前的值 (a
) - 或者您传递给 reduce 的第二个参数(初始值)
[].reduce(function(a, b) { ... }, 0);
^ callback ^ initial value
a
将保留之前每次迭代的结果,因此要获得所有成本的总和,只需添加 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);
使用 es6 语法你可以把它变成一个内衬
var totalExpense = expense.reduce((a, {cost}) => a + cost, 0);
无论下一个 a
应该是什么,您都需要 return
。 a.cost + b.cost
是一个数字。它没有 cost
属性,因此 a.cost
在第一次迭代后将是 undefined
。
只需提供一个起始值0
。还可以考虑为您的参数指定更合适的名称。
var totalExpense = expense.reduce(function(sum, item){
return sum + item.cost;
}, 0);
您需要一个初始值。 reduce函数将累加值作为第一个参数,集合的下一个元素作为第二个
var totalExpense = expense.reduce(function(accumulator, current) {
console.log({ accumulator: accumulator, currentCost: current.cost });
return accumulator + current.cost;
}, 0);
console.log({ totalExpense: totalExpense });
expense.reduce((sum, cur) => ({ cost: sum.cost + cur.cost })).cost;
已更新
正如@Viktor 指出的那样,我之前没有考虑过特殊情况。
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;
}
您可以在 TypeError: Reduce of empty array with no initial value | MDN
中了解更多信息
我正在尝试了解 reduce 的工作原理
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);
这给出 totalExpense 为 NaN
。
输出:
1499 2499
undefined 400
undefined 700
undefined 300
NaN
当我用一个简单的费用数组执行相同的操作时,它工作正常。
这是使用通用函数 foldMap
实现的另一种方法 – 有关此漂亮函数的更多指导,我推荐 this video。
const totalExpense =
expense.foldMap (item => item.cost, 0)
console.log (totalExpense)
// 5398
为此,您需要定义 Array.prototype.foldMap
和 Number.prototype.concat
– 但此实现及其定义位置由您决定
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
}
这是一个有效的代码粘贴
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
您需要提供一个包含 cost
字段的初始值,以便在累加器中引用它。您需要 return 该对象:
expense.reduce(function(acc, curr){
console.log(acc.cost, curr.cost);
acc.cost += curr.cost;
return acc;
}, { cost: 0 });
注意使用比 a
和 b
更有意义的变量名。这将使您的代码更易于理解。 Array.prototype.reduce
回调应该有一个累加器和当前值。这样命名它们以帮助您自己。初始值提供了一个带有 cost
字段的对象,您可以在其中记下您的累计值。
请注意,如果您愿意,也可以在此处使用普通变量。如果您实际上不需要对象:
var total = expense.reduce(function(acc, curr){
acc += curr.cost;
return acc;
}, 0);
console.log(total);
>> 5398
您传递给 reduce 的回调的第一个参数是先前的值 (a
) - 或者您传递给 reduce 的第二个参数(初始值)
[].reduce(function(a, b) { ... }, 0);
^ callback ^ initial value
a
将保留之前每次迭代的结果,因此要获得所有成本的总和,只需添加 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);
使用 es6 语法你可以把它变成一个内衬
var totalExpense = expense.reduce((a, {cost}) => a + cost, 0);
无论下一个 a
应该是什么,您都需要 return
。 a.cost + b.cost
是一个数字。它没有 cost
属性,因此 a.cost
在第一次迭代后将是 undefined
。
只需提供一个起始值0
。还可以考虑为您的参数指定更合适的名称。
var totalExpense = expense.reduce(function(sum, item){
return sum + item.cost;
}, 0);
您需要一个初始值。 reduce函数将累加值作为第一个参数,集合的下一个元素作为第二个
var totalExpense = expense.reduce(function(accumulator, current) {
console.log({ accumulator: accumulator, currentCost: current.cost });
return accumulator + current.cost;
}, 0);
console.log({ totalExpense: totalExpense });
expense.reduce((sum, cur) => ({ cost: sum.cost + cur.cost })).cost;
已更新 正如@Viktor 指出的那样,我之前没有考虑过特殊情况。
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;
}
您可以在 TypeError: Reduce of empty array with no initial value | MDN
中了解更多信息