簡體   English   中英

如何對 JavaScript 對象的值求和?

[英]How to sum the values of a JavaScript object?

我想總結一個對象的值。

我已經習慣了 python 的位置:

sample = { 'a': 1 , 'b': 2 , 'c':3 };
summed =  sum(sample.itervalues())     

以下代碼有效,但代碼很多:

function obj_values(object) {
  var results = [];
  for (var property in object)
    results.push(object[property]);
  return results;
}

function list_sum( list ){
  return list.reduce(function(previousValue, currentValue, index, array){
      return previousValue + currentValue;
  });
}

function object_values_sum( obj ){
  return list_sum(obj_values(obj));
}

var sample = { a: 1 , b: 2 , c:3 };
var summed =  list_sum(obj_values(a));
var summed =  object_values_sum(a)

我是否遺漏了任何明顯的東西,或者就是這樣?

它可以很簡單:

const sumValues = obj => Object.values(obj).reduce((a, b) => a + b);

引用 MDN:

Object.values()方法返回給定對象自己的可枚舉屬性值的數組,其順序與for...in循環提供的順序相同(不同之處在於 for-in 循環枚舉原型鏈中的屬性以及)。

來自MDN 上的Object.values()

reduce()方法對累加器和數組的每個值(從左到右)應用一個函數,以將其減少為單個值。

來自MDN 上的Array.prototype.reduce()

你可以像這樣使用這個函數:

sumValues({a: 4, b: 6, c: -5, d: 0}); // gives 5

請注意,此代碼使用了一些舊版瀏覽器(如 IE)不支持的一些 ECMAScript 功能。 你可能需要使用Babel來編譯你的代碼。

您可以將它們全部放在一個函數中:

 function sum( obj ) { var sum = 0; for( var el in obj ) { if( obj.hasOwnProperty( el ) ) { sum += parseFloat( obj[el] ); } } return sum; } var sample = { a: 1 , b: 2 , c:3 }; var summed = sum( sample ); console.log( "sum: "+summed );


為了好玩,這里是另一個使用Object.keys()Array.reduce()的實現(瀏覽器支持不再是一個大問題):

 function sum(obj) { return Object.keys(obj).reduce((sum,key)=>sum+parseFloat(obj[key]||0),0); } let sample = { a: 1 , b: 2 , c:3 }; console.log(`sum:${sum(sample)}`);

但這似乎要慢得多: jsperf.com

如果您使用的是 lodash,您可以執行類似的操作

_.sum(_.values({ 'a': 1 , 'b': 2 , 'c':3 })) 

常規for循環非常簡潔:

var total = 0;

for (var property in object) {
    total += object[property];
}

如果您修改了原型,您可能必須添加object.hasOwnProperty

現在你可以使用reduce函數並得到總和。

 const object1 = { 'a': 1 , 'b': 2 , 'c':3 } console.log(Object.values(object1).reduce((a, b) => a + b, 0));

老實說,鑒於我們的“現代”,我會盡可能采用函數式編程方法,如下所示:

const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);

我們的累加器acc從值 0 開始,正在累加我們對象的所有循環值。 這具有不依賴於任何內部或外部變量的額外好處; 它是一個常量函數,因此不會被意外覆蓋……為 ES2015 贏得勝利!

您不只是使用簡單for...in循環的任何原因?

var sample = { a: 1 , b: 2 , c:3 };
var summed = 0;

for (var key in sample) {
    summed += sample[key];
};

http://jsfiddle.net/vZhXs/

 let prices = { "apple": 100, "banana": 300, "orange": 250 }; let sum = 0; for (let price of Object.values(prices)) { sum += price; } alert(sum)

但是,如果您需要更強大和更靈活的解決方案,那么我對聚會有點遲鈍,那么這是我的貢獻。 如果您只想對嵌套對象/數組組合中的特定屬性求和,以及執行其他聚合方法,那么這是我在 React 項目中使用的一個小函數:

var aggregateProperty = function(obj, property, aggregate, shallow, depth) {
    //return aggregated value of a specific property within an object (or array of objects..)

    if ((typeof obj !== 'object' && typeof obj !== 'array') || !property) {
        return;
    }

    obj = JSON.parse(JSON.stringify(obj)); //an ugly way of copying the data object instead of pointing to its reference (so the original data remains unaffected)
    const validAggregates = [ 'sum', 'min', 'max', 'count' ];
    aggregate = (validAggregates.indexOf(aggregate.toLowerCase()) !== -1 ? aggregate.toLowerCase() : 'sum'); //default to sum

    //default to false (if true, only searches (n) levels deep ignoring deeply nested data)
    if (shallow === true) {
        shallow = 2;
    } else if (isNaN(shallow) || shallow < 2) {
        shallow = false;
    }

    if (isNaN(depth)) {
        depth = 1; //how far down the rabbit hole have we travelled?
    }

    var value = ((aggregate == 'min' || aggregate == 'max') ? null : 0);
    for (var prop in obj) {
        if (!obj.hasOwnProperty(prop)) {
            continue;
        }

        var propValue = obj[prop];
        var nested = (typeof propValue === 'object' || typeof propValue === 'array');
        if (nested) {
            //the property is an object or an array

            if (prop == property && aggregate == 'count') {
                value++;
            }

            if (shallow === false || depth < shallow) {
                propValue = aggregateProperty(propValue, property, aggregate, shallow, depth+1); //recursively aggregate nested objects and arrays
            } else {
                continue; //skip this property
            }
        }

        //aggregate the properties value based on the selected aggregation method
        if ((prop == property || nested) && propValue) {
            switch(aggregate) {
                case 'sum':
                    if (!isNaN(propValue)) {
                        value += propValue;
                    }
                    break;
                case 'min':
                    if ((propValue < value) || !value) {
                        value = propValue;
                    }
                    break;
                case 'max':
                    if ((propValue > value) || !value) {
                        value = propValue;
                    }
                    break;
                case 'count':
                    if (propValue) {
                        if (nested) {
                            value += propValue;
                        } else {
                            value++;
                        }
                    }
                    break;
            }
        }
    }

    return value;
}

它是遞歸的,非 ES6,它應該可以在大多數半現代瀏覽器中工作。 你像這樣使用它:

const onlineCount = aggregateProperty(this.props.contacts, 'online', 'count');

參數分解:

obj = 對象或數組
property = 您希望對其執行聚合方法的嵌套對象/數組中的屬性
aggregate = 聚合方法(sum、min、max 或 count)
shallow = 可以設置為 true/false 或數值
depth = 應為空或未定義(用於跟蹤后續的遞歸回調)

如果您知道不需要搜索深度嵌套的數據,則可以使用 Shallow 來提高性能。 例如,如果您有以下數組:

[
    {
        id: 1,
        otherData: { ... },
        valueToBeTotaled: ?
    },
    {
        id: 2,
        otherData: { ... },
        valueToBeTotaled: ?
    },
    {
        id: 3,
        otherData: { ... },
        valueToBeTotaled: ?
    },
    ...
]

如果您想避免循環遍歷 otherData 屬性,因為您要聚合的值沒有嵌套那么深,您可以將 shallow 設置為 true。

使用 Lodash

 import _ from 'Lodash'; var object_array = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}]; return _.sumBy(object_array, 'c') // return => 9

在嘗試解決類似問題時,我從@jbabey 遇到了這個解決方案。 稍加修改,我就做對了。 在我的例子中,對象鍵是數字(489)和字符串(“489”)。 因此,為了解決這個問題,每個鍵都被解析。 以下代碼有效:

var array = {"nR": 22, "nH": 7, "totB": "2761", "nSR": 16, "htRb": "91981"}
var parskey = 0;
for (var key in array) {
    parskey = parseInt(array[key]);
    sum += parskey;
};
return(sum);

一個ramda one 班輪:

import {
 compose, 
 sum,
 values,
} from 'ramda'

export const sumValues = compose(sum, values);

使用: const summed = sumValues({ 'a': 1 , 'b': 2 , 'c':3 });

我們可以使用in關鍵字迭代對象,並且可以執行任何算術運算。

 // input const sample = { 'a': 1, 'b': 2, 'c': 3 }; // var let sum = 0; // object iteration for (key in sample) { //sum sum += (+sample[key]); } // result console.log("sum:=>", sum);

通過解析 Integer 對對象鍵值求和。 將字符串格式轉換為整數並對值求和

 var obj = { pay: 22 }; obj.pay; console.log(obj.pay); var x = parseInt(obj.pay); console.log(x + 20);

一個簡單的解決方案是使用 for..in 循環來查找總和。

function findSum(obj){
  let sum = 0;
  for(property in obj){
    sum += obj[property];
  }
  return sum;
}


var sample = { a: 1 , b: 2 , c:3 };
console.log(findSum(sample));

function myFunction(a) { return Object.values(a).reduce((sum, cur) => sum + cur, 0); }

function totalAmountAdjectives(obj) {
    let sum = 0;
    for(let el in obj) {
            sum += el.length;
    }
    return sum;
}
console.log(totalAmountAdjectives({ a: "apple" }))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM