जावास्क्रिप्ट ऑब्जेक्ट के मूल्यों को कैसे योग करें?


86

मैं एक वस्तु के मूल्यों को योग करना चाहता हूं।

मैं अजगर का उपयोग कर रहा हूँ जहाँ यह बस होगा:

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)

क्या मुझे कुछ स्पष्ट याद आ रहा है, या यह सिर्फ ऐसा ही है?

जवाबों:


75

आप इसे एक समारोह में रख सकते हैं:

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


वापसी राशि + parseFloat (obj [कुंजी] || 0) falsey या नल जाँच करने के लिए / खाली मान
सुमित

1
महान काम समाधान के बीच प्रदर्शन अंतर पर प्रकाश डाला। जबकि यह Object.keys().reduceबहुत अधिक सुंदर लग रहा है, यह 60% धीमा है।
दोपहर

101

यह उतना ही सरल हो सकता है:

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

एमडीएन का हवाला देते हुए:

यह Object.values()विधि किसी दिए गए ऑब्जेक्ट के स्वयं के असंख्य गुण मानों की एक सरणी देती है, उसी क्रम में जो for...inलूप द्वारा प्रदान किया गया है (अंतर यह है कि फॉर-लूप प्रोटोटाइप श्रृंखला में गुणों को शामिल करता है)।

से Object.values()MDN पर

reduce()विधि एक संचायक के खिलाफ एक समारोह और (बाएं से दाएं से) सरणी के प्रत्येक मान की एकल मूल्य को कम करने के लिए लागू होता है।

से Array.prototype.reduce()MDN पर

आप इस फ़ंक्शन का उपयोग इस तरह कर सकते हैं:

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

ध्यान दें कि यह कोड कुछ ECMAScript सुविधाओं का उपयोग करता है जो कुछ पुराने ब्राउज़रों (जैसे IE) द्वारा समर्थित नहीं हैं। अपने कोड को संकलित करने के लिए आपको बैबल का उपयोग करना पड़ सकता है ।


3
इसके लिए आवश्यक है कि आप एक 60K पुस्तकालय खींच बस के लिए Object.values()है, जो एक साथ polyfilled किया जाएगा forफ़ायरफ़ॉक्स के अलावा हर ब्राउज़र पर पाश। पॉलीफ़िल के बिना भी, यह forमेरे लिए एक नियमित लूप की तुलना में 4 गुना धीमा है ।
ब्लेंडर

10
@ ब्लेंडर वैसे भी आपको बैबल का उपयोग करने की आवश्यकता है यदि आप किसी भी नई इम्मास्क्रिप्ट सुविधा का उपयोग करना चाहते हैं और अभी भी पुराने ब्राउज़रों का समर्थन करते हैं। इसके अलावा, यदि कोई 2 साल बाद इस प्रश्न का उदाहरण देता है, तो आधुनिक ब्राउज़र शायद Object.values()उस समय तक लागू हो जाएगा ।
मिकेल पेरोलाकोव्स्की

स्वीकृत उत्तर में एक समान दृष्टिकोण है, लेकिन फ़ंक्शन reduceथोड़ा अधिक मूर्खतापूर्ण प्रतीत होता है। क्या आपने उद्देश्य पर विचार करना छोड़ दिया है?
सेरेब्रस

@Cerbrus मैंने मान लिया कि उस वस्तु के सभी मूल्य संख्याएँ हैं।
मिशैल पेरोलाकोव्स्की

12
@ ब्लेंडर ऐसा लगता है कि मैं सही था - डेढ़ साल बीत गए, और Object.values()सभी आधुनिक ब्राउज़रों द्वारा समर्थित है
मिशैल पेरोलाकोव्स्की

25

यदि आप लॉश का उपयोग कर रहे हैं तो आप कुछ ऐसा कर सकते हैं

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

20

एक नियमित forलूप बहुत संक्षिप्त है:

var total = 0;

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

object.hasOwnPropertyयदि आपने प्रोटोटाइप को संशोधित किया है तो आपको इसमें जोड़ना पड़ सकता है ।


14

ईमानदारी से, हमारे "आधुनिक समय" को देखते हुए मैं जब भी संभव हो, एक कार्यात्मक प्रोग्रामिंग दृष्टिकोण के साथ जाऊंगा, जैसे:

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

हमारा संचायक acc, 0 के मान से शुरू होकर, हमारे ऑब्जेक्ट के सभी लूप किए गए मानों को जमा कर रहा है। यह किसी भी आंतरिक या बाहरी चर पर निर्भर नहीं होने का अतिरिक्त लाभ है; यह एक निरंतर कार्य है इसलिए यह गलती से नहीं लिखा जाएगा ... ES2015 के लिए जीतें!


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

मैं पार्टी के लिए थोड़ा तनावपूर्ण हूं, हालांकि, यदि आपको अधिक मजबूत और लचीले समाधान की आवश्यकता है, तो यहां मेरा योगदान है। यदि आप किसी नेस्टेड ऑब्जेक्ट / एरे कॉम्बो में केवल एक विशिष्ट प्रॉपर्टी को समेटना चाहते हैं, साथ ही साथ अन्य एग्रीगेट तरीके भी करते हैं, तो यहाँ एक छोटा सा फंक्शन है जो मैं एक रिएक्ट प्रोजेक्ट पर उपयोग कर रहा हूँ:

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

यह पुनरावर्ती, गैर ईएस 6 है, और इसे अधिकांश अर्ध-आधुनिक ब्राउज़रों में काम करना चाहिए। आप इसे इस तरह उपयोग करते हैं:

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

पैरामीटर टूटने:

obj = या तो एक वस्तु या एक सरणी
संपत्ति = नेस्टेड ऑब्जेक्ट्स / सरणियों के भीतर की संपत्ति जिसे आप कुल विधि = समग्र विधि (योग, अधिकतम, या गणना) उथले पर
एकत्रित करना चाहते हैं = या तो सही पर सेट किया जा सकता है / गलत या एक संख्यात्मक मान गहराई = अशक्त या अपरिभाषित छोड़ दिया जाना चाहिए (इसका उपयोग बाद के पुनरावर्ती कॉलबैक को ट्रैक करने के लिए किया जाता है)


उथले का उपयोग प्रदर्शन को बढ़ाने के लिए किया जा सकता है यदि आप जानते हैं कि आपको गहराई से नेस्टेड डेटा खोजने की आवश्यकता नहीं होगी। उदाहरण के लिए यदि आपके पास निम्न सरणी है:

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

यदि आप अन्यडेटा संपत्ति के माध्यम से लूपिंग से बचना चाहते थे, क्योंकि आप जो मूल्य एकत्र करने जा रहे हैं, वह इतना गहरा नहीं है कि आप उथले को सही पर सेट कर सकें।




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

हम का उपयोग कर वस्तु पुनरावृति कर सकते हैं में कीवर्ड और किसी भी गणित आपरेशन प्रदर्शन कर सकते हैं।

// 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

पार्स इंटेगर द्वारा ऑब्जेक्ट कुंजी मूल्य का योग। स्ट्रिंग स्वरूप को पूर्णांक में बदलना और मूल्यों को समेटना

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.