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


87

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

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

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)

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

답변:


77

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

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


return sum + parseFloat (obj [key] || 0) to check the falsey or null / blank values
sumit

1
솔루션 간의 성능 차이를 강조했습니다. 동안 Object.keys().reduce훨씬 더 우아한 외모, 그것은 60 % 느립니다.
micnguyen

104

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

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 을 사용해야 할 수도 있습니다 .


3
이렇게하면 60K 라이브러리를 당길 필요 단지 가지고 Object.values()로모그래퍼 polyfilled 될 것입니다, for파이어 폭스 이외의 모든 브라우저에서 루프를. 폴리 필이 없어도 일반 for루프 보다 4 배 더 느립니다 .
Blender

10
당신은 당신이 사용하려는 경우 어쨌든 바벨을 사용할 필요가 @Blender 어떤 새로운 ECMAScript를 기능을 여전히 오래된 브라우저를 지원합니다. 게다가, 누군가가 2 년 후에이 질문을 방문한다면, 최신 브라우저는 아마도 Object.values()그 시간까지 구현 될 것입니다 .
Michał Perłakowski

허용되는 답변은 매우 유사한 접근 방식을 가지고 있지만 전달 된 함수 reduce는 좀 더 완벽 해 보입니다. 의도적으로 구문 분석을 생략 했습니까?
Cerbrus

@Cerbrus 나는 그 객체의 모든 값이 숫자라고 가정했습니다.
Michał Perłakowski

12
@Blender 내가 옳은 것 같습니다. 1 년 반이 지났고 Object.values()모든 최신 브라우저에서 지원됩니다 .
Michał Perłakowski

25

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

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

20

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

var total = 0;

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

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


15

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

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

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


13

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

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

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


12

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


1

나는 파티에 약간 지각하지만 더 강력하고 유연한 솔루션이 필요하면 여기에 내 기여가 있습니다. 중첩 된 객체 / 배열 콤보에서 특정 속성 만 합산하고 다른 집계 메서드를 수행하려면 다음은 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 = 물체 또는 어레이 어느
속성 = 당신의 집계 방법을 수행하도록하려는 중첩 객체 / 배열 내의 속성
집합체 = 집계 방법 (합, 최소, 최대, 또는 카운트)
를 얕게 = 중 참 /으로 설정 될 수있다 false 또는 숫자 값
깊이 = null 또는 정의되지 않은 상태 여야합니다 (이후 재귀 콜백을 추적하는 데 사용됨).

깊이 중첩 된 데이터를 검색 할 필요가 없다는 것을 알고있는 경우 Shallow를 사용하여 성능을 향상시킬 수 있습니다. 예를 들어 다음 배열이있는 경우 :

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

집계 할 값이 그렇게 깊게 중첩되지 않았기 때문에 otherData 속성을 반복하지 않으려면 shallow를 true로 설정할 수 있습니다.




0

비슷한 문제를 해결하는 동안 @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);

0

ramda의 하나 라이너 :

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

export const sumValues = compose(sum, values);

사용하다: const summed = sumValues({ 'a': 1 , 'b': 2 , 'c':3 });


0

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


0

Integer를 구문 분석하여 개체 키 값을 더합니다. 문자열 형식을 정수로 변환하고 값 합산

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.