Lua तालिका में प्रविष्टियों की संख्या कैसे प्राप्त करें?


132

लगता है कि "मुझे आपके लिए इसे Google करने दें" सवाल है, लेकिन किसी तरह मुझे इसका जवाब नहीं मिल रहा है। Lua #ऑपरेटर केवल पूर्णांक कुंजियों के साथ प्रविष्टियाँ गिनता है, और ऐसा ही करता है table.getn:

tbl = {}
tbl["test"] = 47
tbl[1] = 48
print(#tbl, table.getn(tbl))   -- prints "1     1"

count = 0
for _ in pairs(tbl) do count = count + 1 end
print(count)            -- prints "2"

मुझे सभी प्रविष्टियों की संख्या की गिनती के बिना कैसे मिल सकता है?


3
@lhf: मैंने एक धारावाहिक लिखा है जो उसके द्वारा देखी गई प्रत्येक वस्तु को याद करता है, और अगली बार जब वह देखता है तो वह वस्तु के बजाय पूर्णांक संदर्भ का उत्सर्जन करता है। प्राकृतिक तरीके से इस लिखने के लिए की तरह कुछ है dictionary[value] = #dictionary + 1, जहां #की संख्या का प्रतिनिधित्व करता है सभी वस्तुओं। क्या मैं क्यों आप है नहीं है यह हैं: सभी में समझदार # (kaizer.se द्वारा उत्तर देखें) के लिए उपयोग के मामलों, सभी वस्तुओं की गिनती एकदम वही है जिसे # पहले से ही रिटर्न के बराबर; ऐसा लगता है कि # सब कुछ बनाने के लिए कड़ाई से एक सुधार है। बेशक मैं एक लुआ नौसिखिया हूँ और इस बिंदु को याद कर रहा हूँ।
रोमन स्टार्कोव

32
@lhf: प्रोग्रामर की काबिलियत पर सवाल उठाना आप के लिए अच्छा नहीं है, यह पूछकर कि उसे कुछ ऐसा करने की ज़रूरत है, जिसके लिए सभी उचित प्रोग्रामिंग भाषाओं का एक सरल कार्य है।
टिमवी

5
@ टिमी: लुआ भाषा के लेखकों में से एक को यह बताना आपके लिए अच्छा नहीं है कि लुआ "उचित" प्रोग्रामिंग भाषाओं में से नहीं है। ;-) बीटीडब्लू, मुझे कभी भी उस जानकारी की आवश्यकता नहीं थी।
अलेक्जेंडर ग्लैडीश

5
मुझे नहीं लगता कि मैंने कभी किसी एक भाषा की हर सुविधा का उपयोग किया है । इसका मतलब यह नहीं है कि वे दूसरों के लिए उपयोगी नहीं हैं :)
रोमन स्टार्कोव

7
@ सिल्वानार मेरी राय में, #ऑपरेटर सिर्फ बीमार है। यह इतनी आसानी से #तय करने योग्य है : सबसे पहले, नियतात्मक बनाएं , और दूसरी बात, रफ़ू गिनती प्राप्त करने के लिए एक नया ऑपरेटर या फ़ंक्शन शुरू करें। कहानी का अंत ... उन्हें इतना जिद्दी क्यों होना पड़ता है? :)
रोमन स्टार्कोव

जवाबों:


129

आपके पास पहले से ही प्रश्न में समाधान है - एकमात्र तरीका पूरी तालिका को पुनरावृत्त करना है pairs(..)

function tablelength(T)
  local count = 0
  for _ in pairs(T) do count = count + 1 end
  return count
end

इसके अलावा, ध्यान दें कि "#" ऑपरेटर की परिभाषा इससे थोड़ी अधिक जटिल है। मुझे इस तालिका को ले कर स्पष्ट करें:

t = {1,2,3}
t[5] = 1
t[9] = 1

मैनुअल के अनुसार, 3, 5 और 9 में से कोई भी इसके लिए मान्य परिणाम हैं #t। इसका उपयोग करने का एकमात्र सामान्य तरीका शून्य मानों के बिना एक सन्निहित भाग के सरणियों के साथ है।


42
मैं अभी भी लूआ के साथ अपने अनुभव की याद में थरथराता हूं, जब मुझे पहली बार महसूस हुआ कि मूल ऑपरेटर की वापसी मूल्य #निर्धारित नहीं है।
रोमन स्टार्कोव

5
ओह, यह निश्चित रूप से नियतात्मक है। यह बिल्कुल वैसी ही बात है जब C मानक कार्यान्वयन परिभाषित व्यवहार के लिए कुछ छोड़ता है। इसका कारण यह है कि विभिन्न कार्यान्वयनकर्ता अलग-अलग कार्यान्वयन विकल्प चुन सकते हैं।
नाकाबिल

19
According to the manual, any of 3, 5 and 9 are valid results for #t। मैनुअल के अनुसार, गैर-अनुक्रमों पर कॉल करना अपरिभाषित है । इसका मतलब है कि कोई भी परिणाम (-1, 3, 3.14, 5, 9) मान्य है।
क्यूबसप्लि 42

6
मान्य परिणामों के बारे में: u0b34a0f6ae Lua 5.1 के लिए सही है, जबकि क्यूब 5.2 के लिए क्यूबसप्ला 42 सही है। किसी भी मामले में, पूरी तरह से पूरी तरह से पागल है।
जेरेमी

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

21

आप प्रविष्टियों की संख्या को ट्रैक करने के लिए एक मेटा-टेबल सेट कर सकते हैं, यह पुनरावृत्ति से तेज हो सकता है यदि यह जानकारी अक्सर आवश्यक हो।


क्या इस पद्धति के साथ प्रविष्टियों को मिटाने का एक सुविधाजनक तरीका है?
u0b34a0f6ae

अफसोस की बात है, यह प्रतीत होता है कि __newindex फ़ंक्शन शून्य असाइनमेंट पर फायर नहीं करता है जब तक कि इंडेक्स मौजूद नहीं है, इसलिए ऐसा लगता है कि आपको एक विशेष फ़ंक्शन के माध्यम से प्रवेश हटाने की फ़नल होगी।
इरगिस

1
आपको एक अलग तालिका में डेटा संग्रहीत करना चाहिए (उदाहरण के लिए __index और __newindex के लिए upvalue के रूप में सुलभ)। तब दोनों __index और __newindex प्रत्येक टेबल एक्सेस के लिए फायर करेंगे। आपको यह देखना चाहिए कि प्रदर्शन स्वीकार्य है या नहीं।
अलेक्जेंडर ग्लैडीश

@Alexander: आह हाँ, और फिर अगले ठोकर बिंदु: यदि आप तालिका को प्रॉक्सी करते हैं, तो जोड़े द्वारा सामान्य पुनरावृत्ति काम नहीं करती है। यह लूवा 5.2 में हल करना संभव होगा, मैंने सुना।
u0b34a0f6ae

5.2 में __pairs और __ipairs metamethods होंगे ... यदि आप इसे 5.1 में करना चाहते हैं, तो आपको जोड़े () फ़ंक्शन को अपने स्वयं के साथ बदलना होगा। लेकिन यह शायद बहुत ज्यादा है। :-)
अलेक्जेंडर ग्लैडिस

3

एक तरीका है, लेकिन यह निराशाजनक हो सकता है: गिनती को संग्रहीत करने के लिए एक अतिरिक्त चर (या तालिका के क्षेत्र में से एक) का उपयोग करें, और हर बार जब आप प्रविष्टि बनाते हैं तो इसे बढ़ाएं।

count = 0
tbl = {}

tbl["test"] = 47
count = count + 1

tbl[1] = 48
count = count + 1

print(count)   -- prints "2"

कोई अन्य तरीका नहीं है, # ऑपरेटर केवल सरणी-जैसे तालिकाओं पर लगातार कुंजियों के साथ काम करेगा।


3
यह एक छद्म तालिका और मेटामेथोड्स के
आरबेरिटिग

मुझे टिप्पणियों से यह आभास हुआ कि समीपवर्ती / मेटामेथोड्स चीज़ इस परिदृश्य का पूरी तरह से समर्थन नहीं करती है, इसलिए मैं इसे वर्तमान में उपलब्ध सर्वोत्तम तरीके के रूप में स्वीकार करूँगा।
रोमन स्टार्कोव

तालिकाओं के लिए गिनती ही एकमात्र तरीका है, और तालिकाओं को बनाते समय एक पंक्ति जोड़ना एक फ़ंक्शन से बेहतर है कि उन्हें हर बार गिनें जब आपको गिनती की आवश्यकता हो। आप गणना पर सेट मान के साथ अंत में एक कुंजी जोड़ सकते हैं।
हेनरिक एरलैंडसन

2

सबसे आसान तरीका जो मुझे पता है कि एक तालिका में प्रविष्टियों की संख्या प्राप्त करने के लिए '#' के साथ है। #tableName को उन प्रविष्टियों की संख्या मिलती है, जब तक वे क्रमांकित हैं:

tbl={
    [1]
    [2]
    [3]
    [4]
    [5]
}
print(#tbl)--prints the highest number in the table: 5

अफसोस की बात है, अगर वे गिने नहीं हैं, यह काम नहीं करेगा।


2

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

इसने कई ऐसे फंक्शन को लागू किया है जिनकी हमें प्रोग्रामिंग करते समय और लुआ में लापता होने की आवश्यकता हो सकती है।

यहाँ इसका उपयोग करने के लिए नमूना है।

> tablex = require "pl.tablex"
> a = {}
> a[2] = 2
> a[3] = 3 
> a['blah'] = 24

> #a
0

> tablex.size(a)
3

1
local function CountedTable(x)
    assert(type(x) == 'table', 'bad parameter #1: must be table')

    local new_t = {}
    local mt = {}

    -- `all` will represent the number of both
    local all = 0
    for k, v in pairs(x) do
        all = all + 1
    end

    mt.__newindex = function(t, k, v)
        if v == nil then
            if rawget(x, k) ~= nil then
                all = all - 1
            end
        else
            if rawget(x, k) == nil then
                all = all + 1
            end
        end

        rawset(x, k, v)
    end

    mt.__index = function(t, k)
        if k == 'totalCount' then return all
        else return rawget(x, k) end
    end

    return setmetatable(new_t, mt)
end

local bar = CountedTable { x = 23, y = 43, z = 334, [true] = true }

assert(bar.totalCount == 4)
assert(bar.x == 23)
bar.x = nil
assert(bar.totalCount == 3)
bar.x = nil
assert(bar.totalCount == 3)
bar.x = 24
bar.x = 25
assert(bar.x == 25)
assert(bar.totalCount == 4)

1
उत्तर पोस्ट करते समय, कोड की न्यूनतम राशि पोस्ट करने की सिफारिश की जाती है जो सीधे एक प्रश्न का उत्तर देती है, और बताती है कि कोड प्रश्न का उत्तर कैसे देता है। यहाँ देखें
cst1992

__newindexकेवल तब कॉल करें जब कोई नई कुंजी परिभाषित हो, इसलिए __newindexजब हम nilकिसी मौजूद कुंजी पर सेट होते हैं तो कॉल करने का कोई अवसर नहीं होता है।
फ्रैंक एके

-1

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

mytable = {}
element1 = {version = 1.1}
element2 = {version = 1.2}
table.insert(mytable, element1)
table.insert(mytable, element2)
print(table.getn(mytable))

यह 2 सही ढंग से प्रिंट करेगा

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