एक सरणी में एक संपत्ति मूल्य का योग करने का बेहतर तरीका


184

मेरे पास कुछ इस तरह है:

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

उत्तर

मैंने @ gruff-bunny सुझाव का उपयोग करने का निर्णय लिया, इसलिए मैं मूल ऑब्जेक्ट (Array) को प्रोटोटाइप करने से बचता हूं

मैंने सिर्फ उनके जवाब में थोड़ा संशोधन किया और सरणी को मान्य किया और योग करने का मूल्य शून्य नहीं है, यह मेरा अंतिम कार्यान्वयन है:

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

2
आप अपने पोस्ट कर सकते हैं उत्तर एक के रूप में इस सवाल का जवाब
केन किन

जवाबों:


124

अद्यतन उत्तर

अर्रे प्रोटोटाइप में एक फ़ंक्शन जोड़ने के सभी डाउनसाइड्स के कारण, मैं इस विकल्प को एक विकल्प प्रदान करने के लिए अपडेट कर रहा हूं जो वाक्यविन्यास के समान सिंटैक्स रखता है जो मूल रूप से प्रश्न में अनुरोध किया गया है।

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/


1
धन्यवाद @ sp00m अब मैंने अपने कार्यान्वयन को array.reduce के साथ बदल दिया है जैसे ग्रूफ़-बन्नी ने उत्तर दिया।
nramirez

यदि आपको पुराने ब्राउज़र का समर्थन करने की आवश्यकता है, तो आपको कम फ़ंक्शन को
पॉलीफ़िल

कृपया इसका विस्तार न करें Array.prototypeक्योंकि यह भविष्य में आपके कोड को तोड़ सकता है। क्यों मूल वस्तुओं को एक बुरी प्रथा के रूप में विस्तारित किया जा रहा है?
str

@ बॉटन्स अगर सरणी में एक अशक्त वस्तु है तो क्या होगा?
Obby

228

मुझे पता है कि इस प्रश्न का एक स्वीकृत उत्तर है, लेकिन मुझे लगा कि मैं एक विकल्प के साथ चिप लगाऊंगा , जिसमें array.reduce का उपयोग किया जाएगा , यह देखते हुए कि एक सरणी को कम करने के लिए विहित उदाहरण है:

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

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

Fiddle


शानदार उत्तर, क्या $scope.travelerTotal = $scope.sum($scope.traveler, 'Amount');नियंत्रक फ़ंक्शन की शुरुआत में इसे रखना संभव है ?
मो।

हाँ यदि यह राशि फ़ंक्शन बनने के बाद आती है।
ग्रूफ़ बनी

14
6 अक्टूबर 2015 को गिरावट का कोई कारण? यदि उत्तर में कोई समस्या है तो कृपया टिप्पणी जोड़ें और मैं इसे सही करूंगा। कोई भी व्यक्ति गुमनामी से नहीं सीखता है।
ग्रूफ़ बनी

यह NaN में परिणाम कर सकता है, अगर सरणी में ऑब्जेक्ट में से किसी एक में प्रोप मौजूद नहीं है (अपरिभाषित)। मुझे नहीं पता कि यह सबसे अच्छा जाँच है, लेकिन इसने मेरे मामले के लिए काम किया: फ़ंक्शन (आइटम, प्रोप) {रिटर्न आइटम्स ।्रेड्यूस (फ़ंक्शन (ए, बी) {अगर (! (एनएएनएन (बी [प्रोप])) {! a + b [Prop];} और {{a}}, 0) लौटाएं; }
क्लेडट्रॉनिकॉन

129

बस एक और लेना, यह वही है जो nativeजावास्क्रिप्ट कार्य करता है 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.

4
return Number(item.Amount);केवल नंबर की जांच करने के लिए
diEcho

4
मैं केवल prevकम फ़ंक्शन में चर के नाम के साथ बहस करूंगा । मेरे लिए, इसका मतलब है कि आपको सरणी में पिछला मान मिल रहा है। लेकिन वास्तव में यह सभी पिछले मूल्यों की कमी है। मुझे पसंद है accumulator, aggregatorया sumSoFarस्पष्टता के लिए।
कारपिडिएम

93

मैं हमेशा प्रोटोटाइप विधि बदलने और पुस्तकालय को जोड़ने से बचता हूं, तो यह मेरा समाधान है:

कम ऐरे प्रोटोटाइप विधि का उपयोग करना पर्याप्त है

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

3
दूसरा पैरामीटर (जो प्रारंभिक मूल्य निर्धारित aकरता है) reduceवस्तुओं का उपयोग करते समय चाल करता है : पहले पुनरावृत्ति में, सरणी aका पहला ऑब्जेक्ट नहीं होगा items, इसके बजाय यह होगा 0
पर्ज़ीफ़ाल

एक समारोह के रूप में: const sumBy = (items, prop) => items.reduce((a, b) => +a + +b[prop], 0); उपयोग:sumBy(traveler, 'Amount') // => 235
रफी

2
एक पुराने स्कूल प्रोग्रामर के रूप में, reduceवाक्यविन्यास मुझे पूरी तरह से अप्रिय लगता है। मेरा मस्तिष्क अभी भी "मूल रूप से" इसे बेहतर समझता है:let total = 0; items.forEach((item) => { total += item.price; });
एंड्रीविसआर

1
@AndrWeisR मुझे आपका समाधान सबसे अच्छा लगता है। इसके अलावा देशी के उपयोग के रूप में यह एक ऐसी चर्चा शब्द है जो शायद ही समझा जाता है कि इसका मतलब क्या है। मैंने आपके समाधान के आधार पर कोड की एक और अधिक मूल पंक्ति बनाई और इसने बहुत अच्छा काम किया। let total = 0; items.forEach(item => total += item.price)
इयान पोस्टन फ्रामर

22

मैंने सोचा कि मैं इस पर अपने दो सेंट छोड़ दूंगा: यह उन ऑपरेशनों में से एक है जो हमेशा विशुद्ध रूप से कार्यात्मक होना चाहिए, किसी भी अन्य चर पर भरोसा नहीं करना चाहिए। कुछ पहले से ही एक अच्छा जवाब दिया, का उपयोग कर reduceयहाँ जाने के लिए रास्ता है।

चूंकि हम में से अधिकांश पहले से ही ES2015 सिंटैक्स का उपयोग कर सकते हैं, यहाँ मेरा प्रस्ताव है:

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

हम इसे एक अपरिवर्तनीय फ़ंक्शन बना रहे हैं, जबकि हम इस पर हैं। reduceयहाँ क्या कर रहा है बस यह है: 0संचायक के लिए एक मूल्य के साथ शुरू करें , और इसमें वर्तमान लूप किए गए आइटम का मूल्य जोड़ें।

कार्यात्मक प्रोग्रामिंग और ES2015 के लिए याय! :)


22

बेहतर पठनीयता और उपयोग के लिए वैकल्पिक Mapऔर Reduce:

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

परफेक्ट मेट, "+1"
मयंक पांडेय

डिफ़ॉल्ट मान को कम करने के लिए .reduce(*** => *** + ***, 0);दूसरों का उपयोग करें जो कि "+1" गायब था
FDisk

19

आप निम्न कार्य कर सकते हैं:

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

13

यह मेरे लिए में काम कर रहा है TypeScriptऔर JavaScript:

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

मुझे आशा है कि उपयोगी है।


4

मुझे यकीन नहीं है कि यह अभी तक उल्लेख किया गया है। लेकिन उसके लिए एक लॉश समारोह है। नीचे का स्निपेट जहां आपके योग का गुण है 'मान' है।

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

दोनों काम करेंगे।



1

यहां 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');

1

जावास्क्रिप्ट का उपयोग करके ऑब्जेक्ट की सरणी कैसे करें

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


1

वस्तुओं की सरणी से

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

0

मैं पहले से ही jquery का उपयोग कर रहा था। लेकिन मुझे लगता है कि इसका सहज ज्ञान बस इतना है:

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

यह मूल रूप से @ अक्षरी के उत्तर का केवल एक छोटा-सा संस्करण है।


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