सरणी में कुछ तत्वों को कैसे गिना जाए?


162

मेरे पास एक सरणी है:

[1, 2, 3, 5, 2, 8, 9, 2]

मैं जानना चाहूंगा कि कितने 2s सरणी में हैं।

forलूप के साथ लूपिंग के बिना जावास्क्रिप्ट में इसे करने का सबसे सुरुचिपूर्ण तरीका क्या है ?

जवाबों:


90

बहुत आसान:

var count = 0;
for(var i = 0; i < array.length; ++i){
    if(array[i] == 2)
        count++;
}

53
नहीं, मेरा मतलब है "के लिए" के साथ पाशन के बिना
Leem

9
@ लिम: लूपिंग खराब क्यों है? कुछ बिंदु पर हमेशा लूपिंग होता है। जाहिर है आप एक ऐसा फंक्शन बनाएंगे जो लूप को छुपाता है। ये "मैं नौकरी के लिए सही उपकरण का उपयोग नहीं करना चाहता" -सीमें ने मेरे लिए कभी कोई मतलब नहीं बनाया। और हम तर्क दे सकते हैं कि सबसे सुरुचिपूर्ण क्या है। उदाहरण के लिए, एक फंक्शन प्रति तत्व बनाने के लिए सिर्फ एक मूल्य के साथ तुलना करने के लिए यह सुरुचिपूर्ण नहीं है।
फेलिक्स क्लिंग

2
हंसी के लिए: चेतावनी (eval ('(' + my_array.join ('== 2) + (') + '== 2)')) jsfiddle.net/gaby_de_wilde/gujhmych
user40521

29
ओपी को शायद लगता है कि लूपिंग खराब है क्योंकि यह कोड की 5 पंक्तियां हैं और इसके लिए परस्पर स्थिति की आवश्यकता होती है। एक डेवलपर जो पढ़ने के लिए आता है कि बाद में यह जांचने के लिए कुछ समय बिताना होगा कि वह क्या करता है, और अपने कार्य से ध्यान हटाएं। एक अमूर्त अब तक बेहतर है: const count = countItems(array, 2);और कार्यान्वयन विवरण अंदर तर्क दिया जा सकता है।
joeytwiddle

2
यह सही उत्तर नहीं है क्योंकि प्रश्न स्पष्ट रूप से लूप का उपयोग नहीं करने के लिए कहता है। मेरे समाधान की जाँच करें जो छोरों का कोई उपयोग नहीं करता है। stackoverflow.com/a/44743436/8211014
लुइस ऑरेंटेस

289

[ यह उत्तर थोड़ा दिनांकित है: संपादन पढ़ें ]

कहते हैं अपने मित्रों को नमस्ते: mapऔर filterऔर reduceऔर forEachऔर everyआदि

(मैं केवल कभी-कभी जावास्क्रिप्ट में लूप के लिए लिखता हूं, क्योंकि ब्लॉक-स्तरीय स्कोपिंग गायब है, इसलिए आपको लूप के शरीर के रूप में एक फ़ंक्शन का उपयोग करना होगा, वैसे भी यदि आपको अपने पुनरावृत्ति सूचकांक या मान को कैप्चर करने या क्लोन करने की आवश्यकता होती है। आम तौर पर अधिक कुशल होते हैं, लेकिन कभी-कभी आपको एक बंद करने की आवश्यकता होती है।)

सबसे पठनीय तरीका:

[....].filter(x => x==2).length

(हम .filter(function(x){return x==2}).lengthइसके बजाय लिख सकते थे )

निम्नलिखित अधिक स्थान-कुशल (O (N) के बजाय O (1)) है, लेकिन मुझे यकीन नहीं है कि आप समय के संदर्भ में कितना लाभ / जुर्माना अदा कर सकते हैं (एक निरंतर कारक से अधिक नहीं जब से आप जाते हैं प्रत्येक तत्व ठीक एक बार):

[....].reduce((total,x) => (x==2 ? total+1 : total), 0)

(यदि आपको इस विशेष कोड कोड को ऑप्टिमाइज़ करने की आवश्यकता है, तो कुछ ब्राउज़रों के लिए लूप तेज़ हो सकता है ... आप jperper.com पर चीजों का परीक्षण कर सकते हैं।)


आप तब सुरुचिपूर्ण हो सकते हैं और इसे एक प्रोटोटाइप फ़ंक्शन में बदल सकते हैं:

[1, 2, 3, 5, 2, 8, 9, 2].count(2)

ऐशे ही:

Object.defineProperties(Array.prototype, {
    count: {
        value: function(value) {
            return this.filter(x => x==value).length;
        }
    }
});

आप उपरोक्त संपत्ति परिभाषा के अंदर नियमित पुरानी लूप तकनीक (अन्य उत्तर देखें) को फिर से चिपका सकते हैं (फिर, यह संभवतः बहुत तेज़ होगा)।


2017 संपादित करें :

वूप्स, यह उत्तर सही उत्तर की तुलना में अधिक लोकप्रिय हो गया है। वास्तव में, बस स्वीकृत उत्तर का उपयोग करें। हालांकि यह उत्तर प्यारा हो सकता है, लेकिन js कंपाइलर संभवतः ऐसे मामलों का अनुकूलन नहीं करते (या कल्पना के कारण नहीं कर सकते)। तो आपको वास्तव में लूप के लिए एक सरल लिखना चाहिए:

Object.defineProperties(Array.prototype, {
    count: {
        value: function(query) {
            /* 
               Counts number of occurrences of query in array, an integer >= 0 
               Uses the javascript == notion of equality.
            */
            var count = 0;
            for(let i=0; i<this.length; i++)
                if (this[i]==query)
                    count++;
            return count;
        }
    }
});

आप एक ऐसे संस्करण को परिभाषित कर सकते हैं .countStrictEq(...)जिसमें ===समानता की धारणा का इस्तेमाल किया गया है। समानता की धारणा महत्वपूर्ण हो सकती है कि आप क्या कर रहे हैं! (उदाहरण के लिए [1,10,3,'10'].count(10)==2, क्योंकि जावास्क्रिप्ट में '4' == 4 जैसी संख्याएँ ... इसलिए इसे कॉल करना .countEqया .countNonstrictयह तनाव होता है कि यह ==ऑपरेटर का उपयोग करता है ।)

इसके अलावा अपनी खुद की मल्टीसेट डेटा संरचना (जैसे कि अजगर की ' collections.Counter') का उपयोग करके पहले स्थान पर गिनती करने से बचें।

class Multiset extends Map {
    constructor(...args) {
        super(...args);
    }
    add(elem) {
        if (!this.has(elem))
            this.set(elem, 1);
        else
            this.set(elem, this.get(elem)+1);
    }
    remove(elem) {
        var count = this.has(elem) ? this.get(elem) : 0;
        if (count>1) {
            this.set(elem, count-1);
        } else if (count==1) {
            this.delete(elem);
        } else if (count==0)
            throw `tried to remove element ${elem} of type ${typeof elem} from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)`;
            // alternatively do nothing {}
    }
}

डेमो:

> counts = new Multiset([['a',1],['b',3]])
Map(2) {"a" => 1, "b" => 3}

> counts.add('c')
> counts
Map(3) {"a" => 1, "b" => 3, "c" => 1}

> counts.remove('a')
> counts
Map(2) {"b" => 3, "c" => 1}

> counts.remove('a')
Uncaught tried to remove element a of type string from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)

sidenote: हालाँकि, यदि आप अभी भी कार्यात्मक-प्रोग्रामिंग तरीका चाहते थे (या Array.prototype को ओवरराइड किए बिना एक थ्रैड वन-लाइनर), तो आप इसे आजकल और अधिक लिख सकते हैं [...].filter(x => x==2).length। यदि आप प्रदर्शन के बारे में परवाह करते हैं, तो ध्यान दें कि जबकि यह समान रूप से फॉर-लूप (O (N) समय) के समान प्रदर्शन है, इसमें O (N) अतिरिक्त मेमोरी (O (1) मेमोरी के बजाय) की आवश्यकता हो सकती है क्योंकि यह लगभग निश्चित रूप से एक मध्यवर्ती सरणी उत्पन्न करते हैं और फिर उस मध्यवर्ती सरणी के तत्वों को गिनते हैं।


1
यह एक अच्छा एफपी समाधान है, एकमात्र "समस्या" (ज्यादातर मामलों के लिए अप्रासंगिक) यह एक मध्यवर्ती सरणी बनाता है।
टॉकलैंड

1
@ टॉकलैंड: अगर वह चिंता का विषय है, तो आप कर सकते हैंarray.reduce(function(total,x){return x==value? : total+1 : total}, 0)
Ninjagecko

1
@ninjagecko क्या टर्नरी ऑपरेटर में केवल एक कोलोन नहीं होना चाहिए? [...].reduce(function(total,x){return x==2 ? total+1 : total}, 0)
ए। क्रुगर

2
@ टॉकलैंड शायद फिल्टर एक मध्यवर्ती सरणी नहीं बनाएगा। एक अच्छा अनुकूलन कंपाइलर आसानी से पहचान सकता है कि केवल सरणी की लंबाई का उपयोग किया जाता है। हो सकता है कि वर्तमान में कोई भी जेएस कंपाइलर ऐसा करने के लिए पर्याप्त स्मार्ट नहीं है, लेकिन यह महत्वपूर्ण नहीं है। जैसा कि फाउलर कहते हैं, "अगर कुछ दर्द होता है, तो इसे अधिक करें"। यह खराब कोड लिखकर कंपाइलर कमियों से बचने के लिए अदूरदर्शी है। यदि कंपाइलर बेकार है, तो कंपाइलर को ठीक करें। mlafeldt.github.io/blog/if-it-hurts-do-it-more-often
John

मैं इसे एक इष्टतम 2017 समाधान मानूंगा const count = (list) => list.filter((x) => x == 2).length:। फिर कॉल करके इसका उपयोग करें count(list)जहां सूची संख्या की एक सरणी है। आप const count = (list) => list.filter((x) => x.someProp === 'crazyValue').lengthऑब्जेक्ट के सरणी में क्रेजीवैल्यू के उदाहरणों को गिनने के लिए भी कर सकते हैं। ध्यान दें, यह संपत्ति के लिए एक सटीक मिलान है।
agm1984

71

ES6 JS को अपडेट करें:

ध्यान दें कि आपको हमेशा ट्रिपल बराबर का उपयोग करना चाहिए: ===सही तुलना पाने के लिए:

// Let has local scope
let array = [1, 2, 3, 5, 2, 8, 9, 2]

// Functional filter with an Arrow function
array.filter(x => x === 2).length  // -> 3

जेएस में निम्नलिखित सर्वसम्मत एरो फ़ंक्शन (लैम्बडा फ़ंक्शन):

(x) => {
   const k = 2
   return k * x
}

एकल इनपुट के लिए इस संक्षिप्त रूप में सरलीकृत किया जा सकता है:

x => 2 * x

जहां returnनिहित है।


लूप के लिए es6 का उपयोग करने की तुलना में फ़िल्टर फ़ंक्शन अधिक प्रदर्शनशील है?
निकल्स

1
@ निक्लेस, मुझे लगता है कि यह समान है (जैसा कि दोनों को सभी तत्वों, ओ (एन) की जांच करना है), लेकिन, मुझे लगता है कि यह ब्राउज़र पर निर्भर है और कैश मेमोरी में फिट होने वाले तत्वों और कंप्यूटर की संख्या पर भी। तो, मुझे लगता है कि उत्तर है: "यह जटिल है" :)
सेवर्रिसन

67

2017: अगर किसी को अभी भी सवाल में दिलचस्पी है, तो मेरा समाधान निम्नलिखित है:

const arrayToCount = [1, 2, 3, 5, 2, 8, 9, 2];
const result = arrayToCount.filter(i => i === 2).length;
console.log('number of the found elements: ' + result);


8

यदि आप दर्ज कर रहे हैं या अंडरस्कोर का उपयोग कर रहे हैं तो _.countBy विधि एरे में प्रत्येक मान द्वारा की गई कुल योगों की एक वस्तु प्रदान करेगी। आप इसे एक वन-लाइनर में बदल सकते हैं यदि आपको केवल एक मूल्य की गणना करने की आवश्यकता है:

_.countBy(['foo', 'foo', 'bar'])['foo']; // 2

यह संख्याओं के सरणियों पर भी ठीक काम करता है। आपके उदाहरण के लिए एक-लाइनर होगा:

_.countBy([1, 2, 3, 5, 2, 8, 9, 2])[2]; // 3

5
भारी भरकम। जैसा कि यह सभी अद्वितीय तत्वों के लिए काउंटर बनाता है। बर्बाद किया हुआ भंडारण और समय।
मेटल डेम

5

अजीब तरीका है कि मैं ऐसा करने के बारे में सोच सकता हूं:

(a.length-(' '+a.join(' ')+' ').split(' '+n+' ').join(' ').match(/ /g).length)+1

कहाँ पे:

  • एक सरणी है
  • n सरणी में गणना करने के लिए संख्या है

मेरा सुझाव, थोड़ी देर के लिए या लूप का उपयोग करें ;-)


3

लूप का उपयोग नहीं करने का मतलब आमतौर पर प्रक्रिया को कुछ विधि को सौंपना है जो लूप का उपयोग करता है

यहाँ एक तरह से हमारे पाश से नफरत करने वाला कोडर उसकी घृणा को संतुष्ट कर सकता है, एक कीमत पर:

var a=[1, 2, 3, 5, 2, 8, 9, 2];

alert(String(a).replace(/[^2]+/g,'').length);


/*  returned value: (Number)
3
*/

आप बार-बार इंडेक्सऑफ को भी कॉल कर सकते हैं, यदि यह एक सरणी विधि के रूप में उपलब्ध है, और हर बार खोज पॉइंटर को स्थानांतरित करें।

यह एक नया सरणी नहीं बनाता है, और लूप एक forEach या फ़िल्टर की तुलना में तेज़ है।

यदि आपके पास देखने के लिए एक लाख सदस्य हैं, तो इससे फर्क पड़ सकता है।

function countItems(arr, what){
    var count= 0, i;
    while((i= arr.indexOf(what, i))!= -1){
        ++count;
        ++i;
    }
    return count
}

countItems(a,2)

/*  returned value: (Number)
3
*/

2
आप अपने रेगेक्स को सिर्फ कम कर सकते हैं String(a).match(/2/g).length + 1- हालांकि इससे सावधान रहें या आपका कार्यान्वयन दोहरे अंकों के साथ अच्छा नहीं खेलेगा।
गैरी ग्रीन

2
कैसे के बारे में [2, 22, 2]?
ओडुवन

2

फ़िल्टर के रूप में सरणी फ़ंक्शंस का उपयोग करने वाले अधिकांश पोस्ट किए गए समाधान अपूर्ण हैं क्योंकि वे पैरामीटर नहीं किए गए हैं।

यहां एक ऐसा समाधान जाता है जिसके साथ गणना करने वाला तत्व रन टाइम पर सेट किया जा सकता है।

function elementsCount(elementToFind, total, number){
    return total += number==elementToFind;
}

var ar = [1, 2, 3, 5, 2, 8, 9, 2];
var elementToFind=2;
var result = ar.reduce(elementsCount.bind(this, elementToFind), 0);

इस दृष्टिकोण का लाभ यह है कि आसानी से एक्स के मुकाबले तत्वों की संख्या को गिनने के लिए फ़ंक्शन को बदल सकता है।

आप कम फ़ंक्शन इनलाइन की भी घोषणा कर सकते हैं

var ar = [1, 2, 3, 5, 2, 8, 9, 2];
var elementToFind=2;
var result = ar.reduce(function (elementToFind, total, number){
    return total += number==elementToFind;
}.bind(this, elementToFind), 0);

var elementToFind=2; ... function (elementToFind, total, number){ return total += number==elementToFind; }.bind(this, elementToFind) ...पढ़ने के लिए कठिन है और बस पर कोई लाभ नहीं देता है ... (acc, x) => acc += number == 2...। मुझे हालांकि +=इसके बजाय आपका उपयोग पसंद है acc + (number == 2)। हालांकि एक अज्ञात वाक्यविन्यास हैक की तरह लगता है।
मास्टरएक्सिलो

2

वास्तव में, आपको इसकी आवश्यकता क्यों होगी mapया इसके filterलिए क्या होगा? reduceइस तरह के ऑपरेशन के लिए "जन्म" था:

[1, 2, 3, 5, 2, 8, 9, 2].reduce( (count,2)=>count+(item==val), 0);

बस! (यदि item==valप्रत्येक पुनरावृत्ति में, तो 1 को संचयकर्ता में जोड़ा जाएगा count, जैसा trueकि हल होगा 1)।

एक समारोह के रूप में:

function countInArray(arr, val) {
   return arr.reduce((count,item)=>count+(item==val),0)
}

या, आगे बढ़ें और अपने सरणियों का विस्तार करें:

Array.prototype.count = function(val) {
   return this.reduce((count,item)=>count+(item==val),0)
}

2

इसे फंक्शन में लपेटना बेहतर है:

let countNumber = (array,specificNumber) => {
    return array.filter(n => n == specificNumber).length
}

countNumber([1,2,3,4,5],3) // returns 1

2

यहाँ O (N) में सभी सरणी वस्तुओं के लिए मायने रखने के लिए एक ES2017 + तरीका है:

const arr = [1, 2, 3, 5, 2, 8, 9, 2];
const counts = {};

arr.forEach((el) => {
  counts[el] = counts[el] ? (counts[el] += 1) : 1;
});

आप वैकल्पिक रूप से आउटपुट को सॉर्ट भी कर सकते हैं:

const countsSorted = Object.entries(counts).sort(([_, a], [__, b]) => a - b);

कंसोल.लॉग (मायने रखता है) आपके उदाहरण सरणी के लिए:

[
  [ '2', 3 ],
  [ '1', 1 ],
  [ '3', 1 ],
  [ '5', 1 ],
  [ '8', 1 ],
  [ '9', 1 ]
]

1

मेरा मानना ​​है कि आप जो देख रहे हैं वह कार्यात्मक दृष्टिकोण है

    const arr = ['a', 'a', 'b', 'g', 'a', 'e'];
    const count = arr.filter(elem => elem === 'a').length;
    console.log(count); // Prints 3

एलएम === 'ए' एक शर्त है, इसे अपने स्वयं के साथ बदलें।


यह 3 नहीं count = arr.filter(elem => elem === 'a').lengthcount = arr.filter(elem => {return elem === 'a'}).length
छपेगा

1

मैं js ऐरे के कम फ़ंक्शन का एक शुरुआती प्रशंसक हूं।

const myArray =[1, 2, 3, 5, 2, 8, 9, 2];
const count = myArray.reduce((count, num) => num === 2 ? count + 1 : count, 0)

वास्तव में यदि आप वास्तव में फैंसी प्राप्त करना चाहते हैं तो आप ऐरे प्रोटोटाइप पर एक गिनती फ़ंक्शन बना सकते हैं। तब आप इसका पुन: उपयोग कर सकते हैं।

Array.prototype.count = function(filterMethod) {
  return this.reduce((count, item) => filterMethod(item)? count + 1 : count, 0);
} 

फिर करो

const myArray =[1, 2, 3, 5, 2, 8, 9, 2]
const count = myArray.count(x => x==2)

0

पुनरावृत्ति द्वारा समाधान

function count(arr, value) {
   if (arr.length === 1)    {
      return arr[0] === value ? 1 : 0;
   } else {
      return (arr.shift() === value ? 1 : 0) + count(arr, value);
   }
}

count([1,2,2,3,4,5,2], 2); // 3

1
क्या यह एक खाली सरणी को संभालता है?
एंड्रयू ग्रिम

@AndrewGrimm के पास यह अधिकार है। बेस केस गिरफ्तारी है। गति == 0
जस्टिन

अच्छा समाधान! मैं केवल अभ्यास के लिए पुनरावृत्ति का उपयोग करके कुछ करने की कोशिश कर रहा था और आपका उदाहरण मैं जो कर रहा था उससे अधिक सुरुचिपूर्ण था। यह निश्चित रूप से उपयोग करने की तुलना में एक अधिक जटिल तरीका है filter, reduceया एक सरल forLoop, और भी, प्रदर्शन को देखते हुए अधिक महंगा है, लेकिन फिर भी इसे पुनरावृत्ति के साथ करने का एक शानदार तरीका है। मेरा एकमात्र परिवर्तन यह है: मुझे लगता है कि यह एक फ़ंक्शन बनाने और सरणी को कॉपी करने और मूल सरणी के एक उत्परिवर्तन से बचने के लिए इसके अंदर एक फिल्टर जोड़ने के लिए बेहतर होगा, फिर आंतरिक फ़ंक्शन के रूप में पुनरावर्ती का उपयोग करें।
आर।

0

var arrayCount = [1,2,3,2,5,6,2,8];
var co = 0;
function findElement(){
    arrayCount.find(function(value, index) {
      if(value == 2)
        co++;
    });
    console.log( 'found' + ' ' + co + ' element with value 2');
}

मैं ऐसा कुछ करूंगा:

var arrayCount = [1,2,3,4,5,6,7,8];

function countarr(){
  var dd = 0;
  arrayCount.forEach( function(s){
    dd++;
  });

  console.log(dd);
}


0

कोर स्तर की फाइल में ऐरे क्लास के लिए एक नया तरीका बनाएँ और इसे अपनी परियोजना में इस्तेमाल करें।

// say in app.js
Array.prototype.occurrence = function(val) {
  return this.filter(e => e === val).length;
}

इसे अपने प्रोजेक्ट में कहीं भी उपयोग करें -

[1, 2, 4, 5, 2, 7, 2, 9].occurrence(2);
// above line returns 3

0

यहाँ जावास्क्रिप्ट में एक लाइनर है।

  1. मानचित्र का उपयोग करें। (v === 2)सरणी में मेल खाने वाले मान खोजें , जो लोगों और शून्य का एक सरणी लौटाते हैं।
  2. उपयोग कम करें। कुल संख्या के लिए सरणी के सभी मूल्यों को मिलाएं।
[1, 2, 3, 5, 2, 8, 9, 2]
  .map(function(v) {
    return v === 2 ? 1 : 0;
  })
  .reduce((a, b) => a + b, 0);

परिणाम है 3


0

निर्भर करता है कि आप इसे कैसे चलाना चाहते हैं:

const reduced = (array, val) => { // self explanatory
    return array.filter((element) => element === val).length;
}

console.log(reduced([1, 2, 3, 5, 2, 8, 9, 2], 2));

// 3

const reducer = (array) => { // array to set > set.forEach > map.set
    const count = new Map();
    const values = new Set(array);
    values.forEach((element)=> {
        count.set(element, array.filter((arrayElement) => arrayElement === element).length);
    });
    return count;
}
console.log(reducer([1, 2, 3, 5, 2, 8, 9, 2]));

// Map(6) {1 => 1, 2 => 3, 3 => 1, 5 => 1, 8 => 1, …}

-7

आप जावास्क्रिप्ट सरणी में लंबाई संपत्ति का उपयोग कर सकते हैं:

var myarray = [];
var count = myarray.length;//return 0

myarray = [1,2];
count = myarray.length;//return 2

यदि आप इसे पहले फिल्टर करते हैं तो आप लंबाई का उपयोग कर सकते हैं। अर्थात् सरणी.फिल्टर (x => x === 2) .length
स्कॉट ब्लैंच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.