खोज…
वाक्य - विन्यास
- ipairs (num_table) - संख्यात्मक सूचकांकों के साथ Lua तालिका
- जोड़े (input_table) - सामान्य Lua तालिका पुनरावृत्ति
- कुंजी, मान = अगला (input_table, input_key) - लुआ तालिका मूल्य चयनकर्ता
- table.insert (input_table, [position], value) - इनपुट तालिका में निर्दिष्ट मान डालें
- remove_value = table.remove (input_table, [position]) - अंतिम या स्थिति द्वारा निर्दिष्ट मान निकालें
टिप्पणियों
Lua में उपलब्ध टेबल्स केवल अंतर्निहित डेटा संरचना हैं। यह या तो सुरुचिपूर्ण सादगी या भ्रामक है, इस पर निर्भर करता है कि आप इसे कैसे देखते हैं।
एक Lua तालिका कुंजी-मूल्य जोड़े का एक संग्रह है जहां कुंजियाँ अद्वितीय हैं और न तो कुंजी और न ही मूल्य nil
। जैसे, एक Lua तालिका एक शब्दकोश, हैशमैप या अन्य भाषाओं से साहचर्य सरणी जैसा दिख सकता है। टेबल के साथ कई संरचनात्मक पैटर्न बनाए जा सकते हैं: ढेर, कतार, सेट, सूचियां, रेखांकन आदि। अंत में, टेबल का उपयोग लुआ में कक्षाएं बनाने और एक मॉड्यूल सिस्टम बनाने के लिए किया जा सकता है।
तालिकाओं का उपयोग कैसे किया जाता है, इस पर कोई विशेष नियम लागू नहीं करता है। एक तालिका में निहित वस्तुएं Lua प्रकारों का मिश्रण हो सकती हैं। इसलिए, उदाहरण के लिए, एक तालिका में मान या कुंजी के रूप में तार, फ़ंक्शन, बूलियन, संख्याएं, और यहां तक कि अन्य तालिकाएं हो सकती हैं ।
1 के साथ लगातार सकारात्मक पूर्णांक कुंजी के साथ एक Lua तालिका में एक अनुक्रम है कहा जाता है। सकारात्मक पूर्णांक कुंजियों के साथ कुंजी-मूल्य जोड़े अनुक्रम के तत्व हैं। अन्य भाषाएं इसे 1-आधारित सरणी कहती हैं। कुछ मानक संचालन और फ़ंक्शंस केवल एक तालिका के अनुक्रम पर काम करते हैं और कुछ बिना अनुक्रम के टेबल पर लागू होने पर गैर-नियतात्मक व्यवहार करते हैं।
nil
तालिका में मान सेट करना तालिका से निकाल देता है। Iterators अब संबंधित कुंजी नहीं देखेंगे। जब किसी अनुक्रम के साथ तालिका के लिए कोडिंग करते हैं, तो अनुक्रम को तोड़ने से बचना महत्वपूर्ण है; केवल अंतिम तत्व को हटा दें या मानक table.remove
तरह एक फ़ंक्शन का उपयोग करें। table.remove
, जो तत्वों को अंतराल को बंद करने के लिए स्थानांतरित करता है।
टेबल बनाना
एक खाली तालिका बनाना इस प्रकार सरल है:
local empty_table = {}
आप साधारण सारणी के रूप में एक तालिका भी बना सकते हैं:
local numeric_table = {
"Eve", "Jim", "Peter"
}
-- numeric_table[1] is automatically "Eve", numeric_table[2] is "Jim", etc.
ध्यान रखें कि डिफ़ॉल्ट रूप से, तालिका अनुक्रमण 1 से शुरू होता है।
संभव भी साहचर्य तत्वों के साथ एक तालिका बना रहा है:
local conf_table = {
hostname = "localhost",
port = 22,
flags = "-Wall -Wextra"
clients = { -- nested table
"Eve", "Jim", "Peter"
}
}
नीचे दिए गए उपयोग के लिए सिंटैक्स चीनी है। इस उदाहरण में कुंजियाँ प्रकार, स्ट्रिंग की हैं। उपरोक्त सिंटैक्स को अभिलेखों के रूप में प्रकट करने के लिए जोड़ा गया था। यह रिकॉर्ड-शैली सिंटैक्स स्ट्रिंग कुंजी के साथ तालिकाओं को अनुक्रमित करने के लिए सिंटैक्स द्वारा समान है, जैसा कि 'बुनियादी उपयोग' ट्यूटोरियल में देखा गया है।
जैसा कि टिप्पणी अनुभाग में बताया गया है, रिकॉर्ड-शैली वाक्यविन्यास हर संभव कुंजी के लिए काम नहीं करता है। इसके अतिरिक्त एक कुंजी किसी भी प्रकार का कोई भी मूल्य हो सकता है, और पिछले उदाहरणों में केवल तार और अनुक्रमिक संख्याएं शामिल हैं। अन्य मामलों में आपको स्पष्ट वाक्यविन्यास का उपयोग करने की आवश्यकता होगी:
local unique_key = {}
local ops_table = {
[unique_key] = "I'm unique!"
["^"] = "power",
[true] = true
}
तालिकाओं को निष्क्रिय करना
Lua मानक पुस्तकालय एक pairs
फ़ंक्शन प्रदान करता है जो एक तालिका की कुंजियों और मूल्यों पर निर्भर करता है। जब pairs
साथ पुनरावृत्ति होती है, तो ट्रैवर्सल के लिए कोई निर्दिष्ट आदेश नहीं होता है, भले ही तालिका की चाबियाँ संख्यात्मक हों ।
for key, value in pairs(input_table) do
print(key, " -- ", value)
end
संख्यात्मक कुंजियों का उपयोग करने वाली तालिकाओं के लिए, Lua एक ipairs
फ़ंक्शन प्रदान करता है। जब तक पहला nil
मान नहीं मिलता, तब तक ipairs
फ़ंक्शन table[1]
, table[2]
इत्यादि से ipairs
: ipairs
होगा।
for index, value in ipairs(numeric_table) do
print(index, ". ", value)
end
चेतावनी दी जाती है कि कुछ मौकों पर आप चाहें तो ipairs()
का उपयोग करके पुनरावृत्ति काम नहीं करेगी:
input_table
में "छेद" है। (अधिक जानकारी के लिए "सारणी के रूप में प्रयुक्त तालिकाओं से बचने के अंतराल पर अनुभाग देखें"। उदाहरण के लिए:table_with_holes = {[1] = "value_1", [3] = "value_3"}
चाबियाँ सभी संख्यात्मक नहीं थीं। उदाहरण के लिए:
mixed_table = {[1] = "value_1", ["not_numeric_index"] = "value_2"}
बेशक, निम्नलिखित एक तालिका के लिए भी काम करता है जो एक उचित अनुक्रम है:
for i = 1, #numeric_table do
print(i, ". ", numeric_table[i])
end
अंकीय सारणी को उल्टे क्रम में बदलना आसान है:
for i = #numeric_table, 1, -1 do
print(i, ". ", numeric_table[i])
end
तालिकाओं पर पुनरावृत्ति करने का एक अंतिम तरीका लूप के for
जेनेरिक में next
चयनकर्ता का उपयोग करना है। pairs
तरह ट्रैवर्सल के लिए कोई निर्दिष्ट आदेश नहीं है। ( pairs
तरीका next
आंतरिक रूप से उपयोग करता है। इसलिए next
का उपयोग अनिवार्य रूप से pairs
का एक अधिक मैन्युअल संस्करण है। लूआ के संदर्भ मैनुअल में pairs
और next
विवरण के लिए लूआ के संदर्भ मैनुअल में देखें।)
for key, value in next, input_table do
print(key, value)
end
मूल उपयोग
बेसिक टेबल उपयोग में टेबल एलीमेंट्स को एक्सेस करना और असाइन करना, टेबल कंटेंट को जोड़ना और टेबल कंटेंट को हटाना शामिल है। ये उदाहरण मानते हैं कि आप टेबल बनाना जानते हैं।
एक्सेस करने वाले तत्व
निम्नलिखित तालिका को देखते हुए,
local example_table = {"Nausea", "Heartburn", "Indigestion", "Upset Stomach",
"Diarrhea", cure = "Pepto Bismol"}
इंडेक्स सिंटैक्स का उपयोग करके तालिका के अनुक्रमिक भाग को अनुक्रमित किया जा सकता है, इंडेक्स सिंटैक्स का तर्क वांछित कुंजी-मूल्य जोड़ी की कुंजी है। जैसा कि निर्माण ट्यूटोरियल में बताया गया है, अधिकांश घोषणा सिंटैक्स कुंजी-मूल्य जोड़े घोषित करने के लिए सिंटैक्टिक चीनी है। क्रमिक रूप से शामिल तत्व, जैसे example_table
में पहले पाँच मान, कुंजियों के रूप में बढ़ते पूर्णांक मान का उपयोग करें; रिकॉर्ड सिंटैक्स फ़ील्ड के नाम को स्ट्रिंग के रूप में उपयोग करता है।
print(example_table[2]) --> Heartburn
print(example_table["cure"]) --> Pepto Bismol
स्ट्रिंग कुंजियों के लिए तालिका निर्माण में स्ट्रिंग कुंजियों के लिए रिकॉर्ड-शैली सिंटैक्स को समानांतर करने के लिए सिंटैक्स चीनी है। निम्नलिखित दो पंक्तियाँ समतुल्य हैं।
print(example_table.cure) --> Pepto Bismol
print(example_table["cure"]) --> Pepto Bismol
आप उन कुंजियों का उपयोग करके तालिकाओं तक पहुंच सकते हैं जिनका आपने पहले उपयोग नहीं किया है, जो कि अन्य भाषाओं की तरह त्रुटि नहीं है। ऐसा करने से डिफ़ॉल्ट मान nil
।
तत्वों को सौंपना
आप इंडेक्स सिंटैक्स का उपयोग करके किसी तालिका में असाइन करके मौजूदा तालिका तत्वों को संशोधित कर सकते हैं। इसके अतिरिक्त, रिकॉर्ड-शैली अनुक्रमण सिंटैक्स मूल्यों को भी सेट करने के लिए उपलब्ध है
example_table.cure = "Lots of water, the toilet, and time"
print(example_table.cure) --> Lots of water, the toilet, and time
example_table[2] = "Constipation"
print(example_table[2]) --> Constipation
आप असाइनमेंट का उपयोग करके किसी मौजूदा तालिका में नए तत्व भी जोड़ सकते हैं।
example_table.copyright_holder = "Procter & Gamble"
example_table[100] = "Emergency source of water"
विशेष टिप्पणी: कुछ तार रिकॉर्ड-सिंटैक्स के साथ समर्थित नहीं हैं। विवरण के लिए टिप्पणी अनुभाग देखें।
तत्वों को निकालना
जैसा कि पहले कहा गया है, बिना किसी निर्धारित मूल्य के कुंजी के लिए डिफ़ॉल्ट मान nil
। किसी तालिका से एक तत्व को हटाना उतना ही सरल है जितना कि एक कुंजी का मान डिफ़ॉल्ट मान पर रीसेट करना।
example_table[100] = "Face Mask"
तत्व अब एक अप्राप्य तत्व से अप्रभेद्य हैं।
तालिका की लंबाई
टेबल्स केवल साहचर्य सरणियों हैं (टिप्पणी देखें), लेकिन जब सन्निहित पूर्णांक कुंजियों का उपयोग 1 से शुरू होता है, तो तालिका में अनुक्रम कहा जाता है।
किसी तालिका के अनुक्रम भाग की लंबाई का पता लगाकर #
का उपयोग किया जाता है:
local example_table = {'a', 'l', 'p', 'h', 'a', 'b', 'e', 't'}
print(#example_table) --> 8
आप आसानी से एक अनुक्रम तालिका में आइटम संलग्न करने के लिए लंबाई ऑपरेशन का उपयोग कर सकते हैं।
example_table[#example_table+1] = 'a'
print(#example_table) --> 9
उपरोक्त उदाहरण में, #example_table
का पिछला मान 8
, 1
को जोड़ने पर आपको अनुक्रम में अगली वैध पूर्णांक कुंजी मिलती है, 9
, इसलिए ... example_table[9] = 'a'
। यह टेबल की किसी भी लम्बाई के लिए काम करता है।
विशेष टिप्पणी: पूर्णांक कुंजियों का उपयोग करना, जो कि सन्निहित नहीं हैं और 1 से शुरू होकर तालिका को एक विरल तालिका में बना देती है। उस स्थिति में लंबाई ऑपरेशन का परिणाम अपरिभाषित है। टिप्पणी अनुभाग देखें।
तत्वों को जोड़ने / हटाने के लिए टेबल लाइब्रेरी फ़ंक्शंस का उपयोग करना
एक अन्य तरीका है एक मेज के तत्वों को जोड़ने के लिए है table.insert()
समारोह। डालने का कार्य केवल अनुक्रम तालिकाओं पर काम करता है। फ़ंक्शन को कॉल करने के दो तरीके हैं। पहला उदाहरण पहला उपयोग दिखाता है, जहां कोई तत्व (दूसरा तर्क) डालने के लिए सूचकांक को निर्दिष्ट करता है। यह दिए गए सूचकांक से सभी तत्वों को एक स्थिति में #table
ऊपर #table
। दूसरे उदाहरण से पता चलता है अन्य के उपयोग table.insert()
जहां सूचकांक निर्दिष्ट नहीं है और दिए गए मूल्य तालिका (सूचकांक के अंत में जोड़ा जाता है, #table + 1
)।
local t = {"a", "b", "d", "e"}
table.insert(t, 3, "c") --> t = {"a", "b", "c", "d", "e"}
t = {"a", "b", "c", "d"}
table.insert(t, "e") --> t = {"a", "b", "c", "d", "e"}
तत्वों को हटाने के लिए समानांतर table.insert()
में table.remove()
। इसी प्रकार इसके दो कॉलिंग शब्दार्थ हैं: एक दिए गए स्थान पर तत्वों को हटाने के लिए, और दूसरा अनुक्रम के अंत से हटाने के लिए। किसी अनुक्रम के मध्य से हटाते समय, निम्नलिखित सभी तत्वों को एक सूचकांक से नीचे स्थानांतरित कर दिया जाता है।
local t = {"a", "b", "c", "d", "e"}
local r = table.remove(t, 3) --> t = {"a", "b", "d", "e"}, r = "c"
t = {"a", "b", "c", "d", "e"}
r = table.remove(t) --> t = {"a", "b", "c", "d"}, r = "e"
ये दो कार्य दिए गए तालिका को बदल देते हैं। जैसा कि आप table.insert()
कॉलिंग का दूसरा तरीका बताने में सक्षम हो सकते हैं। table.insert()
और table.remove()
टेबल के लिए स्टैक शब्दार्थ प्रदान करता है। इसका उपयोग करते हुए, आप नीचे दिए गए उदाहरण की तरह कोड लिख सकते हैं।
function shuffle(t)
for i = 0, #t-1 do
table.insert(t, table.remove(t, math.random(#t-i)))
end
end
यह फिशर-येट्स शफल को लागू करता है, शायद अक्षम रूप से। यह उसी तालिका के अंत में बेतरतीब ढंग से निकाले गए तत्व को जोड़ने के लिए table.insert()
का उपयोग करता है, और तालिका के शेष अप्रकाशित हिस्से से एक तत्व को बेतरतीब ढंग से निकालने के लिए table.remove()
।
सारणी के रूप में प्रयुक्त तालिकाओं में अंतराल से बचना
हमारी शर्तों को परिभाषित करना
यहाँ सरणी से हमारा मतलब एक अनुक्रम के रूप में इस्तेमाल की गई एक लुआ तालिका से है। उदाहरण के लिए:
-- Create a table to store the types of pets we like.
local pets = {"dogs", "cats", "birds"}
हम इस तालिका को एक अनुक्रम के रूप में उपयोग कर रहे हैं: पूर्णांकों द्वारा की गई वस्तुओं का एक समूह। कई भाषाओं में यह एक सरणी है, और इसलिए हम करेंगे। लेकिन सख्ती से कहा जाए तो लुआ में एक सरणी जैसी कोई बात नहीं है। बस टेबल हैं, जिनमें से कुछ सरणी-जैसे हैं, जिनमें से कुछ हैश-जैसे (या शब्दकोश-जैसे, यदि आप पसंद करते हैं), और जिनमें से कुछ मिश्रित हैं।
हमारे pets
सरणी के बारे में एक महत्वपूर्ण बात यह है कि कोई अंतराल नहीं है। पहला आइटम, pets[1]
, स्ट्रिंग "कुत्ते", दूसरा आइटम, pets[2]
है, स्ट्रिंग "बिल्लियों" है, और अंतिम आइटम, pets[3]
, "पक्षी" है। Lua के मानक पुस्तकालय और Lua के लिए लिखे गए अधिकांश मॉड्यूल अनुक्रमों के लिए पहले सूचकांक के रूप में 1 मानते हैं। इसलिए एक 1..n
रहित सरणी में अनुक्रम में किसी भी संख्या को 1..n
बिना 1..n
से आइटम हैं। (सीमित मामले में, n = 1
, और सरणी में केवल एक आइटम है।)
लुआ इस तरह की तालिकाओं पर पुनरावृति करने के लिए अंतर्निहित फ़ंक्शन ipairs
प्रदान करता है।
-- Iterate over our pet types.
for idx, pet in ipairs(pets) do
print("Item at position " .. idx .. " is " .. pet .. ".")
end
यह "आइटम 1 स्थिति में कुत्तों" है, मुद्रित करेगा "," स्थिति 2 पर आइटम बिल्लियों है। "," स्थिति 3 पर आइटम पक्षी है। "
लेकिन अगर हम निम्नलिखित करते हैं तो क्या होगा?
local pets = {"dogs", "cats", "birds"}
pets[12] = "goldfish"
for idx, pet in ipairs(pets) do
print("Item at position " .. idx .. " is " .. pet .. ".")
end
इस दूसरे उदाहरण के रूप में एक सरणी एक विरल सरणी है। अनुक्रम में अंतराल हैं। यह सरणी इस तरह दिखती है:
{"dogs", "cats", "birds", nil, nil, nil, nil, nil, nil, nil, nil, "goldfish"}
-- 1 2 3 4 5 6 7 8 9 10 11 12
शून्य मान किसी भी स्मृति को ग्रहण नहीं करते हैं; आंतरिक रूप से लुआ केवल मूल्यों [1] = "dogs"
, [2] = "cats"
, [3] = "birtds"
और [12] = "goldfish"
[3] = "birtds"
तत्काल प्रश्न का उत्तर देने के लिए, पक्षियों के बाद ipairs
बंद हो जाएंगी; जब तक हम अपना कोड समायोजित नहीं करेंगे, तब तक pets[12]
में "सुनहरी मछली" नहीं पहुंचेंगे। इसका कारण यह है कि ipairs
1..n-1
से पुनरावृत्त करता है, जहाँ n
, पहले nil
की स्थिति है। लुआ table[length-of-table + 1]
को परिभाषित करता table[length-of-table + 1]
nil
। एक उचित क्रम में, लुआ जब तीन-आइटम सरणी में चौथा आइटम प्राप्त करने, कहने की कोशिश करता है, तो चलना बंद हो जाता है।
कब?
विरल सरणियों के साथ उत्पन्न होने वाले मुद्दों के लिए दो सबसे सामान्य स्थान हैं (i) जब सरणी की लंबाई निर्धारित करने की कोशिश कर रहे हैं और (ii) सरणी पर पुनरावृति करने की कोशिश कर रहे हैं। विशेष रूप से:
-
#
ऑपरेटर का उपयोग करते समय चूंकि लंबाई ऑपरेटर पहले मिलने वालेnil
पर गिनती करना बंद कर देता है। - जब ऊपर उल्लेख किया गया है तो
ipairs()
फ़ंक्शन का उपयोग करते हुए पाया गया पहलाnil
परipairs()
बंद हो जाता है। - का उपयोग करते समय
table.unpack()
इस विधि पहली बार में खोल बंद हो जाता है के बाद से समारोहnil
पाया। - अन्य कार्यों का उपयोग करते समय जो (प्रत्यक्ष या अप्रत्यक्ष रूप से) उपरोक्त में से किसी का उपयोग करते हैं।
इस समस्या से बचने के लिए, अपना कोड लिखना महत्वपूर्ण है ताकि यदि आप किसी सारणी के सारणी की अपेक्षा करते हैं, तो आप अंतराल का परिचय न दें। अंतराल को कई तरीकों से पेश किया जा सकता है:
- यदि आप किसी सरणी में गलत स्थिति में कुछ जोड़ते हैं।
- यदि आप एक सरणी में एक
nil
मान सम्मिलित करते हैं। - यदि आप किसी सरणी से मान निकालते हैं।
आप सोच सकते हैं, "लेकिन मैं उन चीजों में से कभी नहीं करूंगा।" खैर, जानबूझकर नहीं, लेकिन यहां एक ठोस उदाहरण है कि चीजें कैसे गलत हो सकती हैं। कल्पना कीजिए कि आप लुआ के लिए एक फिल्टर विधि लिखना चाहते हैं जैसे रूबी का select
और पर्ल का grep
। विधि एक परीक्षण फ़ंक्शन और एक सरणी को स्वीकार करेगी। यह एरे पर निर्भर करता है, बदले में प्रत्येक आइटम पर परीक्षण विधि को बुलाता है। यदि आइटम पास होता है, तो उस आइटम को परिणाम सरणी में जोड़ा जाता है जो विधि के अंत में वापस आ जाता है। निम्नलिखित एक छोटी गाड़ी कार्यान्वयन है:
local filter = function (fun, t)
local res = {}
for idx, item in ipairs(t) do
if fun(item) then
res[idx] = item
end
end
return res
end
समस्या यह है कि जब फ़ंक्शन false
, तो हम अनुक्रम में एक नंबर छोड़ते हैं। कॉलिंग filter(isodd, {1,2,3,4,5,6,7,8,9,10})
कल्पना करें filter(isodd, {1,2,3,4,5,6,7,8,9,10})
: रिटर्न टेबल में हर बार अंतराल filter(isodd, {1,2,3,4,5,6,7,8,9,10})
filter
करने के लिए पास की गई संख्या में सम संख्या।
यहाँ एक निश्चित कार्यान्वयन है:
local filter = function (fun, t)
local res = {}
for _, item in ipairs(t) do
if fun(item) then
res[#res + 1] = item
end
end
return res
end
टिप्स
- मानक कार्यों का उपयोग करें:
table.insert(<table>, <value>)
हमेशा सरणी के अंत में संलग्न होता है।table[#table + 1] = value
लिए एक छोटा हाथ है।table.remove(<table>, <index>)
अंतर को भरने के लिए सभी निम्नलिखित मानों को वापस ले जाएगा (जो इसे धीमा भी बना सकता है)। - डालने से पहले
nil
मानों के लिए जाँच करें।table.pack(function_call())
जैसी चीजों से परहेज करें, जो हमारी तालिका मेंnil
मानों को चुपके कर सकते हैं। - डालने के बाद
nil
मानों के लिए जाँच करें, और यदि आवश्यक हो तो सभी लगातार मूल्यों को स्थानांतरित करके अंतराल को भरना। - यदि संभव हो, तो प्लेसहोल्डर मान का उपयोग करें। उदाहरण के लिए,
0
या कुछ अन्य प्लेसहोल्डर मान के लिएnil
बदलें। - यदि अंतराल छोड़ना अपरिहार्य है, तो यह स्पष्ट रूप से प्रलेखित (टिप्पणी) होना चाहिए।
- एक
__len()
लिखें और#
ऑपरेटर का उपयोग करें।
6 के लिए उदाहरण ।:
tab = {"john", "sansa", "daenerys", [10] = "the imp"}
print(#tab) --> prints 3
setmetatable(tab, {__len = function() return 10 end})
-- __len needs to be a function, otherwise it could just be 10
print(#tab) --> prints 10
for i=1, #tab do print(i, tab[i]) end
--> prints:
-- 1 john
-- 2 sansa
-- 3 daenerys
-- 4 nil
-- ...
-- 10 the imp
for key, value in ipairs(tab) do print(key, value) end
--> this only prints '1 john \n 2 sansa \n 3 daenerys'
एक अन्य विकल्प pairs()
फ़ंक्शन का उपयोग करना और गैर-पूर्णांक सूचकांकों को फ़िल्टर करना है:
for key in pairs(tab) do
if type(key) == "number" then
print(key, tab[key]
end
end
-- note: this does not remove float indices
-- does not iterate in order