更好的方法是在数组中对属性值求和

我有这样的东西:

$scope.traveler = [
{  description: 'Senior', Amount: 50},
{  description: 'Senior', Amount: 50},
{  description: 'Adult', Amount: 75},
{  description: 'Child', Amount: 35},
{  description: 'Infant', Amount: 25 },
];

现在,为了得到这个数组的总数量,我做了这样的事情:

$scope.totalAmount = function(){
var total = 0;
for (var i = 0; i < $scope.traveler.length; i++) {
total = total + $scope.traveler[i].Amount;
}
return total;
}

当只有一个数组时,这很容易,但我有其他具有不同属性名的数组,我想要求和。

如果我能做这样的事情,我会更快乐:

$scope.traveler.Sum({ Amount });

但我不知道怎样才能在将来重复使用它:

$scope.someArray.Sum({ someProperty });
423215 次浏览

更新后的答案

由于向Array原型添加函数的所有缺点,我正在更新这个答案,以提供一种替代方案,使语法与问题中最初请求的语法相似。

class TravellerCollection extends Array {
sum(key) {
return this.reduce((a, b) => a + (b[key] || 0), 0);
}
}
const traveler = new TravellerCollection(...[
{  description: 'Senior', Amount: 50},
{  description: 'Senior', Amount: 50},
{  description: 'Adult', Amount: 75},
{  description: 'Child', Amount: 35},
{  description: 'Infant', Amount: 25 },
]);


console.log(traveler.sum('Amount')); //~> 235

原来的答案

因为它是一个数组,你可以添加一个函数到数组原型。

traveler = [
{  description: 'Senior', Amount: 50},
{  description: 'Senior', Amount: 50},
{  description: 'Adult', Amount: 75},
{  description: 'Child', Amount: 35},
{  description: 'Infant', Amount: 25 },
];


Array.prototype.sum = function (prop) {
var total = 0
for ( var i = 0, _len = this.length; i < _len; i++ ) {
total += this[i][prop]
}
return total
}


console.log(traveler.sum("Amount"))

小提琴:http://jsfiddle.net/9BAmj/

我知道这个问题有一个公认的答案,但我想我应该加入一个使用array.reduce的替代方案,看到一个数组的总和是reduce的规范示例:

$scope.sum = function(items, prop){
return items.reduce( function(a, b){
return a + b[prop];
}, 0);
};


$scope.travelerTotal = $scope.sum($scope.traveler, 'Amount');

< a href = " http://jsfiddle.net/GruffBunny/4cFU3/ " > < >强小提琴< /强> < / >

我想我应该在这一点上发表我的意见:这是那些应该始终是纯函数式的操作之一,不依赖于任何外部变量。一些人已经给出了一个很好的答案,使用reduce是这里的方法。

既然我们大多数人已经可以使用ES2015语法,下面是我的建议:

const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
我们正在使它成为一个不可变函数。reduce在这里所做的事情很简单: 从累加器的0值开始,并将当前循环项的值添加到该累加器

函数式编程和ES2015太棒了!:)

只是另一种说法,这就是native JavaScript函数MapReduce的构建目的(Map和Reduce是许多语言中的强大功能)。

var traveler = [{description: 'Senior', Amount: 50},
{description: 'Senior', Amount: 50},
{description: 'Adult', Amount: 75},
{description: 'Child', Amount: 35},
{description: 'Infant', Amount: 25}];


function amount(item){
return item.Amount;
}


function sum(prev, next){
return prev + next;
}


traveler.map(amount).reduce(sum);
// => 235;


// or use arrow functions
traveler.map(item => item.Amount).reduce((prev, next) => prev + next);

请注意:通过创建独立的小函数,我们可以再次使用它们。

// Example of reuse.
// Get only Amounts greater than 0;


// Also, while using Javascript, stick with camelCase.
// If you do decide to go against the standards,
// then maintain your decision with all keys as in...


// { description: 'Senior', Amount: 50 }


// would be


// { Description: 'Senior', Amount: 50 };


var travelers = [{description: 'Senior', amount: 50},
{description: 'Senior', amount: 50},
{description: 'Adult', amount: 75},
{description: 'Child', amount: 35},
{description: 'Infant', amount: 0 }];


// Directly above Travelers array I changed "Amount" to "amount" to match standards.


function amount(item){
return item.amount;
}


travelers.filter(amount);
// => [{description: 'Senior', amount: 50},
//     {description: 'Senior', amount: 50},
//     {description: 'Adult', amount: 75},
//     {description: 'Child', amount: 35}];
//     Does not include "Infant" as 0 is falsey.

我不确定是否有人提到过这一点。但是有一个lodash函数。下面的代码段,其中value是你要求和的属性,是“value”。

_.sumBy(objects, 'value');
_.sumBy(objects, function(o) { return o.value; });

两者都可以。

我总是避免改变原型方法和添加库,所以这是我的解决方案:

采用约简阵列原型法就足够了

// + operator for casting to Number
items.reduce((a, b) => +a + +b.price, 0);

也可以使用Array.prototype.forEach ()

let totalAmount = 0;
$scope.traveler.forEach( data => totalAmount = totalAmount + data.Amount);
return totalAmount;

我已经在用jquery了。但我认为这已经足够直观了:

var total_amount = 0;
$.each(traveler, function( i, v ) { total_amount += v.Amount ; });

这基本上只是@akhouri回答的简写版本。

您可以执行以下操作:

$scope.traveler.map(o=>o.Amount).reduce((a,c)=>a+c);

下面是一个使用ES6箭头函数的一行程序。

const sumPropertyValue = (items, prop) => items.reduce((a, b) => a + b[prop], 0);


// usage:
const cart_items = [ {quantity: 3}, {quantity: 4}, {quantity: 2} ];
const cart_total = sumPropertyValue(cart_items, 'quantity');

如何使用Javascript和对象数组

const traveler = [
{  description: 'Senior', Amount: 50},
{  description: 'Senior', Amount: 50},
{  description: 'Adult', Amount: 75},
{  description: 'Child', Amount: 35},
{  description: 'Infant', Amount: 25 }
];

const traveler = [
{  description: 'Senior', Amount: 50},
{  description: 'Senior', Amount: 50},
{  description: 'Adult', Amount: 75},
{  description: 'Child', Amount: 35},
{  description: 'Infant', Amount: 25 },
];
function sum(arrayData, key){
return arrayData.reduce((a,b) => {
return {Amount : a.Amount + b.Amount}
})
}
console.log(sum(traveler))
' < / p >

用于提高可读性和使用MapReduce的替代方案:

const traveler = [
{  description: 'Senior', amount: 50 },
{  description: 'Senior', amount: 50 },
{  description: 'Adult', amount: 75 },
{  description: 'Child', amount: 35 },
{  description: 'Infant', amount: 25 },
];


const sum = traveler
.map(item => item.amount)
.reduce((prev, curr) => prev + curr, 0);

可重用功能:

const calculateSum = (obj, field) => obj
.map(items => items.attributes[field])
.reduce((prev, curr) => prev + curr, 0);

这里有一个我觉得更灵活的解决办法:

function sumOfArrayWithParameter (array, parameter) {
let sum = null;
if (array && array.length > 0 && typeof parameter === 'string') {
sum = 0;
for (let e of array) if (e && e.hasOwnProperty(parameter)) sum += e[parameter];
}
return sum;
}

要得到和,只需像这样使用它:

let sum = sumOfArrayWithParameter(someArray, 'someProperty');

它在TypeScriptJavaScript中为我工作:

let lst = [
{ description:'Senior', price: 10},
{ description:'Adult', price: 20},
{ description:'Child', price: 30}
];
let sum = lst.map(o => o.price).reduce((a, c) => { return a + c });
console.log(sum);

希望对大家有用。

从对象数组

function getSum(array, column)
let values = array.map((item) => parseInt(item[column]) || 0)
return values.reduce((a, b) => a + b)
}


foo = [
{ a: 1, b: "" },
{ a: null, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
]


getSum(foo, a) == 3
getSum(foo, b) == 6

使用reduce和解构来求和

const traveler = [
{ description: 'Senior', Amount: 50 },
{ description: 'Senior', Amount: 50 },
{ description: 'Adult', Amount: 75 },
{ description: 'Child', Amount: 35 },
{ description: 'Infant', Amount: 25 },
];


console.log(traveler.reduce((n, {Amount}) => n + Amount, 0))
在经过这些答案后,我认为实际上for(或forEachfor ofawait)循环比reduce甚至mapreduce更具可读性。 认为:< / p >
  1. 在6个月后回到这段代码或者由其他人维护它。我认为你使用循环的方法已经足够好了。
  2. 在将来扩展这个函数,以防您想要添加货币转换或类似的功能。在一行代码中执行此操作并不是一个好主意。

var traveler = [
{Amount: 50,  description: 'Senior'},
{Amount: 50,  description: 'Senior'},
{Amount: 75,  description: 'Adult'},
{Amount: 35,  description: 'Child'},
{Amount: 25,  description: 'Infant'}
];


var sumFromArray = (propertyName, array) => {
let sum = 0;
array.forEach(item => {
sum += item[propertyName] ?? 0;
});
return sum;
};


var sumOfTraveler = sumFromArray('Amount', traveler);
console.log(sumOfTraveler);

使用类型你的函数定义可能像这样:

const sumFromArray = (propertyName: string, array: Array<{[propertyName: string]: number}>) => { ... };

更多细节:类型文字中的计算属性名必须直接引用内置符号

我不反对mapreduce或一行程序,这只是思考的食物。

我真的很沮丧,在阅读所有的代码,其中张贴作为一个解决方案,因为我是一个新的是,我试图添加一个功能到一个简单的应用程序的实践。解决这个问题的简单方法是

let testArray = [5, 7, 8, 4];


function(){
sum = 0;
for(let i = 0; i < testArray.length; i++){
sum += testArray[i];
}

//会给你数组的和

你可以在一行中轻松地使用jscollection库进行数据库查询作业 https://github.com/somnathpanja/jscollection < / p >
var total = List.extend(traveler).select('Amount').sum();