البحث عن عنصر في قائمة لوا
سؤال
إذا لدي قائمة من البنود مثل هذا:
local items = { "apple", "orange", "pear", "banana" }
وكيف يمكنني معرفة ما اذا كان "البرتقالي" في هذه القائمة؟
في بيثون ما يمكن القيام به:
if "orange" in items:
# do something
هل هناك ما يعادلها في لوا؟
المحلول
هل يمكن استخدام شيء من هذا القبيل مجموعة من البرمجة في لوا :
function Set (list)
local set = {}
for _, l in ipairs(list) do set[l] = true end
return set
end
وبعد ذلك كنت قد وضعت قائمتك في مجموعة والاختبار للحصول على عضوية:
local items = Set { "apple", "orange", "pear", "banana" }
if items["orange"] then
-- do something
end
وأو هل يمكن تكرار عبر القائمة مباشرة:
local items = { "apple", "orange", "pear", "banana" }
for _,v in pairs(items) do
if v == "orange" then
-- do something
break
end
end
نصائح أخرى
استخدم تمثيل التالي بدلا من ذلك:
local items = { apple=true, orange=true, pear=true, banana=true }
if items.apple then
...
end
وأنت ترى عن كثب واحدة من سلبيات لوا وجود واحد فقط بنية بيانات --- لديك للفة بنفسك. إذا كنت عصا مع لوا سوف تتراكم تدريجيا مكتبة من الوظائف التي تعالج الجداول في الطريقة التي تريد أن تفعل الأشياء. وتضم مكتبتي تحويل القائمة إلى مجموعة والنظام أعلى وظيفة قائمة البحث:
function table.set(t) -- set of list
local u = { }
for _, v in ipairs(t) do u[v] = true end
return u
end
function table.find(f, l) -- find element v of l satisfying f(v)
for _, v in ipairs(l) do
if f(v) then
return v
end
end
return nil
end
والجداول لوا هي البديل عن كثب من القواميس بيثون بدلا من القوائم. الجدول لديك خلق هو في الأساس مجموعة المفهرسة المستندة إلى 1 من السلاسل. استخدام أي خوارزمية البحث المعيارية لمعرفة ما إذا كانت قيمة في المصفوفة. وهناك نهج آخر يتمثل في تخزين القيم كمفاتيح الجدول بدلا كما هو مبين في تنفيذ مجموعة من آخر جون اريكسون و.
function valid(data, array)
local valid = {}
for i = 1, #array do
valid[array[i]] = true
end
if valid[data] then
return false
else
return true
end
end
إليك وظيفة تستخدم لفحص إذا كانت البيانات في صفيف.
ونوع من الحل باستخدام metatable ...
local function preparetable(t)
setmetatable(t,{__newindex=function(self,k,v) rawset(self,v,true) end})
end
local workingtable={}
preparetable(workingtable)
table.insert(workingtable,123)
table.insert(workingtable,456)
if workingtable[456] then
...
end
وهذه هي وظيفة السويسري-armyknife يمكنك استخدامها:
function table.find(t, val, recursive, metatables, keys, returnBool)
if (type(t) ~= "table") then
return nil
end
local checked = {}
local _findInTable
local _checkValue
_checkValue = function(v)
if (not checked[v]) then
if (v == val) then
return v
end
if (recursive and type(v) == "table") then
local r = _findInTable(v)
if (r ~= nil) then
return r
end
end
if (metatables) then
local r = _checkValue(getmetatable(v))
if (r ~= nil) then
return r
end
end
checked[v] = true
end
return nil
end
_findInTable = function(t)
for k,v in pairs(t) do
local r = _checkValue(t, v)
if (r ~= nil) then
return r
end
if (keys) then
r = _checkValue(t, k)
if (r ~= nil) then
return r
end
end
end
return nil
end
local r = _findInTable(t)
if (returnBool) then
return r ~= nil
end
return r
end
ويمكنك استخدامه لمعرفة ما اذا كان وجود قيمة:
local myFruit = "apple"
if (table.find({"apple", "pear", "berry"}, myFruit)) then
print(table.find({"apple", "pear", "berry"}, myFruit)) -- 1
ويمكنك استخدامه للعثور على مفتاح:
local fruits = {
apple = {color="red"},
pear = {color="green"},
}
local myFruit = fruits.apple
local fruitName = table.find(fruits, myFruit)
print(fruitName) -- "apple"
وآمل المعلمة recursive
تتحدث عن نفسها.
والمعلمة metatables
تسمح لك للبحث metatables كذلك.
والمعلمة keys
يجعل نظرة وظيفة مفاتيح في القائمة. بالطبع من شأنها أن تكون ذات جدوى في لوا (يمكنك القيام به فقط fruits[key]
) ولكن جنبا إلى جنب مع recursive
وmetatables
، يصبح في متناول يدي.
والمعلمة returnBool
على بعد حراسة آمنة عندما يكون لديك الجداول التي false
كمفتاح في جدول (نعم هذا ممكن: fruits = {false="apple"}
)