रूबी में गिनती, आकार, लंबाई ... बहुत सारे विकल्प?


140

मुझे इस पर कोई निश्चित उत्तर नहीं मिल रहा है और मैं यह सुनिश्चित करना चाहता हूं कि मैं इसे "n'th स्तर" पर समझ सकूं :-)

    a = {"a" => "नमस्ते", "b" => "विश्व"}
    .काउंट # 2
    a.size # 2
    a.length # 2

    a = [१०, २०]
    .काउंट # 2
    a.size # 2
    a.length # 2

तो कौन सा उपयोग करें? अगर मैं जानना चाहता हूं कि क्या एक से अधिक तत्व हैं तो यह कोई मायने नहीं रखता है, लेकिन मैं यह सुनिश्चित करना चाहता हूं कि मैं वास्तविक अंतर को समझूं। यह सरणियों पर भी लागू होता है। मुझे वही परिणाम मिलते हैं।

इसके अलावा, मुझे पता है कि गिनती / आकार / लंबाई ActiveRecord के साथ अलग-अलग अर्थ है। मैं अभी शुद्ध रूबी (1.92) में दिलचस्पी रखता हूं, लेकिन अगर कोई इस अंतर पर झंकार करना चाहता है, तो एआर बनाता है कि इसकी सराहना की जाएगी।

धन्यवाद!


5
आपके द्वारा सामना की गई घटना को कभी-कभी TMTOWTDI कहा जाता है : इसमें एक से अधिक तरीके होते हैं। यह नारा पर्ल समुदाय से आता है, और पर्ल रूबी के प्रभाव में से एक है।
एंड्रयू ग्रिम

ये आमतौर पर एक दूसरे के लिए उपनाम हैं - वे ऐसा ही करते हैं। एक विधि है जिसे आपको ध्यान में रखना चाहिए: Array#nitemsजो किसी सरणी में गैर-एनआईएल आइटमों की संख्या लौटाता है। लेकिन वह रूबी 1.9 में अब उपलब्ध नहीं है
तिलो

जवाबों:


194

Arrays और hashes के sizeलिए एक उपनाम है length। वे पर्यायवाची हैं और बिल्कुल वही काम करते हैं।

count अधिक बहुमुखी है - यह एक तत्व या विधेय ले सकता है और केवल उन वस्तुओं को गिन सकता है जो मेल खाते हैं।

> [1,2,3].count{|x| x > 2 }
=> 1

उस स्थिति में जहां आप गणना करने के लिए कोई पैरामीटर प्रदान नहीं करते हैं, मूल रूप से कॉलिंग लंबाई के समान प्रभाव होता है। हालांकि प्रदर्शन में अंतर हो सकता है।

हम ऐरे के स्रोत कोड से देख सकते हैं कि वे लगभग एक ही काम करते हैं। यहाँ निम्नलिखित के कार्यान्वयन के लिए C कोड है array.length:

static VALUE
rb_ary_length(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    return LONG2NUM(len);
}

और यहाँ के कार्यान्वयन से प्रासंगिक हिस्सा है array.count:

static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
    long n = 0;

    if (argc == 0) {
        VALUE *p, *pend;

        if (!rb_block_given_p())
            return LONG2NUM(RARRAY_LEN(ary));

        // etc..
    }
}

कोड array.countकुछ अतिरिक्त जांच करता है, लेकिन अंत में ठीक उसी कोड को कॉल करता है LONG2NUM(RARRAY_LEN(ary)):।

दूसरी ओर हैश ( स्रोत कोड ) अपने स्वयं के अनुकूलित संस्करण को लागू करने के लिए नहीं लगता है, countइसलिए Enumerable( स्रोत कोड ) से कार्यान्वयन का उपयोग किया जाता है, जो सभी तत्वों पर ध्यान केंद्रित करता है और उन्हें एक-एक करके गिना जाता है।

सामान्य तौर पर मैं सलाह देता हूं कि आप length(या इसके अन्य नाम size) का उपयोग करें countयदि आप जानना चाहते हैं कि कुल कितने तत्व हैं।


ActiveRecord के बारे में, दूसरे हाथ पर, वहाँ रहे हैं महत्वपूर्ण अंतर। इस पोस्ट को देखें:


10

उन अनुप्रयोगों के लिए एक महत्वपूर्ण अंतर है जो डेटाबेस कनेक्शन का उपयोग करते हैं।

जब आप कई ORM (ActiveRecord, DataMapper, आदि) का उपयोग कर रहे हैं, तो सामान्य समझ यह है कि .साइज़ एक क्वेरी उत्पन्न करेगा जो डेटाबेस से सभी वस्तुओं का अनुरोध करता है ('mytable से * सेलेक्ट करें') और फिर आपको आइटमों की संख्या देता है। परिणामस्वरूप, जबकि .count एक एकल क्वेरी ('चयन योग्य (*) से mytable') उत्पन्न करेगा जो काफी तेज है।

क्योंकि ये ओआरएम कम से कम विस्मय के सिद्धांत का अनुसरण करने के लिए प्रचलित हैं। सामान्य तौर पर अगर मेरे पास पहले से मेमोरी में कुछ है, तो मैं उपयोग करता हूं। आकार दें, और यदि मेरा कोड डेटाबेस (या एपीआई के माध्यम से बाहरी सेवा) के लिए एक अनुरोध उत्पन्न करेगा। मैं इसका उपयोग करता हूं।


1
इसके साथ कुछ विचार करना है counter_cache। यदि आपके पास एक तालिका है, fooऔर इसमें has_many है bar, तो आपके पास fooनाम का एक कॉलम होगा, bars_countजो किसी भी समय अपडेट हो जाता barहै / नष्ट हो जाता है। का उपयोग करके foo.bars.sizeउस कॉलम को चेक किया जाता है (वास्तव में किसी भी प्रश्न के बिना bars)। foo.bars.countवास्तविक क्वेरी करता है, जो कैश के उद्देश्य को हरा देगा।
ड्यूक

7

ज्यादातर मामलों में (जैसे एरे या स्ट्रिंग ) के sizeलिए एक उपनाम है length

countसामान्य रूप से Enumerable से आता है और एक वैकल्पिक विधेय ब्लॉक ले सकता है। इस प्रकार enumerable.count {cond}यह [मोटे तौर पर] है (enumerable.select {cond}).length- यह बेशक मध्यवर्ती संरचना को बायपास कर सकता है क्योंकि इसे बस मिलान की भविष्यवाणी की आवश्यकता है।

नोट: अगर ब्लॉक निर्दिष्ट नहीं किया गया है या यदि संभव हो तो शॉर्ट-सर्किट होने पर एन्यूमरेशन के मूल्यांकन को count मजबूर करता है, तो मुझे यकीन नहीं lengthहै।

संपादित करें (मार्क के जवाब के लिए धन्यवाद!): count एक ब्लॉक के बिना (कम से कम एरे के लिए) एक मूल्यांकन के लिए मजबूर नहीं करता है । मुझे लगता है कि औपचारिक व्यवहार के बिना यह अन्य कार्यान्वयनों के लिए "खुला" है, अगर किसी मूल्यांकन के बिना एक मूल्यांकन के लिए मजबूर करना वास्तव में वैसे भी समझ में आता है।


5

मुझे http://blog.hasmanythrough.com/2008/2/27/count-length-size

ActiveRecord में, यह पता लगाने के कई तरीके हैं कि एक संघ में कितने रिकॉर्ड हैं, और वे कैसे काम करते हैं, इसमें कुछ सूक्ष्म अंतर हैं।

post.comments.count - SQL COUNT क्वेरी के साथ तत्वों की संख्या निर्धारित करें। आप संबद्ध तत्वों के केवल सबसेट को गिनने के लिए शर्तों को भी निर्दिष्ट कर सकते हैं (उदाहरण के लिए: शर्तें => {: author_name => "josh"})। यदि आप एसोसिएशन पर एक काउंटर कैश स्थापित करते हैं, तो #count नई क्वेरी को निष्पादित करने के बजाय उस कैश की गई वैल्यू लौटाएगा।

post.comments.length - यह हमेशा एसोसिएशन की सामग्री को मेमोरी में लोड करता है, फिर लोड किए गए तत्वों की संख्या लौटाता है। ध्यान दें कि यह अपडेट के लिए बाध्य नहीं करेगा यदि एसोसिएशन पहले लोड किया गया था और फिर नए टिप्पणियों को एक अन्य तरीके (जैसे Comment.create (...) के बजाय post.comments.create (...) के माध्यम से बनाया गया था।

post.comments.size - यह दो पिछले विकल्पों के संयोजन के रूप में काम करता है। यदि संग्रह पहले ही लोड हो चुका है, तो वह #length कहते हुए अपनी लंबाई लौटा देगा। यदि इसे अभी तक लोड नहीं किया गया है, तो यह #count कॉल करने जैसा है।

इसके अलावा मेरे पास एक व्यक्तिगत अनुभव है:

<%= h(params.size.to_s) %> # works_like_that !
<%= h(params.count.to_s) %> # does_not_work_like_that !

2

हमारे पास एक सरणी में कितने तत्व हैं .length, .countऔर यह जानने के लिए कई तरीके हैं .size। हालाँकि, इसके array.sizeबजाय इसका उपयोग करना बेहतर है array.count। क्योंकि .sizeप्रदर्शन में बेहतर है।


1

मार्क बायर्स के उत्तर में अधिक जोड़ना। रूबी में विधि एरे # लंबाई विधि के array.sizeलिए एक उपनाम है । इन दोनों विधियों में से किसी का भी उपयोग करने में कोई तकनीकी अंतर नहीं है। संभवतः आपको प्रदर्शन में भी कोई अंतर नहीं दिखेगा। हालाँकि, यह भी वही काम करता है लेकिन कुछ अतिरिक्त कार्यात्मकता के साथ # गिनतीarray.count

इसका उपयोग कुछ स्थिति के आधार पर तत्वों की कुल संख्या प्राप्त करने के लिए किया जा सकता है। गणना को तीन तरीकों से बुलाया जा सकता है:

Array # गिनती # Array में तत्वों की संख्या देता है

Array # count n # Array में n मान रखने वाले तत्वों की संख्या देता है

सरणी # गिनती {| मैं | i.even?} रिटर्न प्रत्येक तत्व सरणी पर लगाए गए शर्त के आधार पर गिनता है

array = [1,2,3,4,5,6,7,4,3,2,4,5,6,7,1,2,4]

array.size     # => 17
array.length   # => 17
array.count    # => 17

यहाँ तीनों विधियाँ समान कार्य करती हैं। हालांकि यहां वह जगह है जहां countदिलचस्प हो जाता है।

आइए हम कहते हैं, मैं यह खोजना चाहता हूं कि मान 2 के साथ कितने सरणी तत्वों को समाहित करता है

array.count 2    # => 3

सरणी में 2 के रूप में मान के साथ कुल तीन तत्व हैं।

अब, मैं सभी सरणी तत्वों को 4 से अधिक खोजना चाहता हूं

array.count{|i| i > 4}   # =>6

सरणी में कुल 6 तत्व हैं जो 4 की तुलना में> हैं।

मुझे उम्मीद है कि यह countविधि के बारे में कुछ जानकारी देता है ।

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