Programing

JavaScript 객체의 값을 합하는 방법은 무엇입니까?

lottogame 2020. 11. 26. 07:44
반응형

JavaScript 객체의 값을 합하는 방법은 무엇입니까?


객체의 값을 합하고 싶습니다.

나는 그것이 바로 파이썬에 익숙합니다.

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)

나는 명백한 것을 놓치고 있습니까, 아니면 이것이 그대로입니까?


모든 것을 하나의 함수에 넣을 수 있습니다.

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()and를 사용하는 또 다른 구현이 있습니다 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


다음과 같이 간단 할 수 있습니다.

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

MDN 인용 :

Object.values()메서드는 for...in루프에서 제공하는 것과 동일한 순서로 주어진 객체의 고유 한 열거 가능한 속성 값의 배열을 반환합니다 (차이점은 for-in 루프가 프로토 타입 체인의 속성도 열거한다는 것입니다).

에서 Object.values()MDN에

reduce()메서드는 누산기 및 배열의 ​​각 값 (왼쪽에서 오른쪽으로)에 대해 함수를 적용하여 단일 값으로 줄입니다.

에서 Array.prototype.reduce()MDN에

이 기능을 다음과 같이 사용할 수 있습니다.

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

이 코드는 일부 이전 브라우저 (예 : IE)에서 지원하지 않는 일부 ECMAScript 기능을 사용합니다. 코드를 컴파일 하려면 Babel 을 사용해야 할 수도 있습니다 .


일반 for루프는 매우 간결합니다.

var total = 0;

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

object.hasOwnProperty프로토 타입을 수정 한 경우 추가해야 할 수 있습니다 .


lodash를 사용하는 경우 다음과 같이 할 수 있습니다.

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

단순한 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/


솔직히 우리의 "현대 시대"를 감안할 때 가능한 한 다음과 같이 함수형 프로그래밍 접근 방식을 사용하겠습니다.

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

우리 누산기 acc값 0으로 시작은 우리의 객체의 반복 값을 축적한다. 이는 내부 또는 외부 변수에 의존하지 않는다는 추가 이점이 있습니다. 상수 함수이므로 실수로 덮어 쓰지 않습니다. ES2015에서 승리하세요!


이제 reduce함수를 사용 하고 합계를 얻을 수 있습니다.

const object1 = { 'a': 1 , 'b': 2 , 'c':3 }

console.log(Object.values(object1).reduce((a, b) => a + b, 0));


나는 파티에 약간 지각하지만 더 강력하고 유연한 솔루션이 필요하면 여기에 내 기여가 있습니다. 중첩 된 객체 / 배열 콤보에서 특정 속성 만 합산하고 다른 집계 메서드를 수행하려면 다음은 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 = either an object or an array
property = the property within the nested objects/arrays you wish to perform the aggregate method on
aggregate = the aggregate method (sum, min, max, or count)
shallow = can either be set to true/false or a numeric value
depth = should be left null or undefined (it is used to track the subsequent recursive callbacks)

Shallow can be used to enhance performance if you know that you will not need to search deeply nested data. For instance if you had the following array:

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

If you wanted to avoid looping through the otherData property since the value you are going to be aggregating is not nested that deeply, you could set shallow to true.


I came across this solution from @jbabey while trying to solve a similar problem. With a little modification, I got it right. In my case, the object keys are numbers (489) and strings ("489"). Hence to solve this, each key is parse. The following code works:

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);

A ramda one liner:

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

export const sumValues = compose(sum, values);

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


Use 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

참고URL : https://stackoverflow.com/questions/16449295/how-to-sum-the-values-of-a-javascript-object

반응형