2009-03-17 42 views
40

Nếu tôi có một danh sách các mục như thế này:Tìm kiếm một mục trong danh sách Lua

local items = { "apple", "orange", "pear", "banana" } 

làm thế nào để kiểm tra xem "màu da cam" là trong danh sách này?

Trong Python tôi có thể làm:

if "orange" in items: 
    # do something 

Có tương đương trong Lua?

Trả lời

63

Bạn có thể sử dụng một cái gì đó giống như một bộ từ Programming in Lua:

function Set (list) 
    local set = {} 
    for _, l in ipairs(list) do set[l] = true end 
    return set 
end 

Sau đó, bạn có thể đặt danh sách của bạn trong Set và thử nghiệm cho thành viên:

local items = Set { "apple", "orange", "pear", "banana" } 

if items["orange"] then 
    -- do something 
end 

Hoặc bạn có thể duyệt qua danh sách trực tiếp :

local items = { "apple", "orange", "pear", "banana" } 

for _,v in pairs(items) do 
    if v == "orange" then 
    -- do something 
    break 
    end 
end 
4

Bảng Lua tương tự chặt chẽ hơn với Python dictio naries chứ không phải là danh sách. Bảng bạn tạo ra về bản chất là một mảng chuỗi được lập chỉ mục dựa trên 1. Sử dụng bất kỳ thuật toán tìm kiếm chuẩn nào để tìm hiểu xem một giá trị có nằm trong mảng hay không. Một cách tiếp cận khác là lưu trữ các giá trị dưới dạng các khóa bảng thay vì được hiển thị trong phần cài đặt của bài viết của Jon Ericson.

22

Sử dụng các đại diện sau đây thay vì:

local items = { apple=true, orange=true, pear=true, banana=true } 
if items.apple then 
    ... 
end 
+2

Đây là cách tốt nhất để thực hiện một bộ (trong toán học thuần túy ý nghĩa) của sự vật ở Lua. Bravo! Tuy nhiên, vì nó không có khái niệm về trật tự, nó không nhất thiết phải trả lời câu hỏi chung về "Tìm kiếm một mục trong danh sách Lua?" nếu thứ tự danh sách quan trọng. – Mark

+0

Điều này cảm thấy thanh lịch hơn rất nhiều. Chỉ cần sử dụng nó để tạo một bảng trông giống như '{thingIAmLookingFor: true, secondThingIAmLookingFor: true}' –

+0

Dường như không hoạt động với các con số. – CalculatorFeline

17

Bạn đang nhìn thấy tận mắt một trong những nhược điểm của Lua chỉ có một cấu trúc dữ liệu --- bạn phải cuộn của riêng bạn. Nếu bạn gắn bó với Lua bạn sẽ dần dần tích lũy một thư viện các hàm thao tác bảng theo cách bạn muốn làm việc. Thư viện của tôi bao gồm một danh sách để thiết lập chuyển đổi và một hàm bậc cao danh sách, tìm kiếm:

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 
+6

Đây không phải là một con của việc có một cấu trúc dữ liệu, nó chỉ là một con của Lua có một thư viện chuẩn crappy. –

1

Sắp xếp các giải pháp sử dụng 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 
+0

Làm thế nào này khác gì so '' 'workingtable local = {} workingtable [123] = true workingtable [456] = true nếu workingtable [456] sau đó ... end''' –

2
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 

Dưới đây là các chức năng tôi sử dụng để kiểm tra xem dữ liệu có nằm trong mảng hay không.

1

Đây là một chức năng swiss-armyknife bạn có thể sử dụng:

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 

Bạn có thể sử dụng nó để kiểm tra xem một giá trị tồn tại:

local myFruit = "apple" 
if (table.find({"apple", "pear", "berry"}, myFruit)) then 
    print(table.find({"apple", "pear", "berry"}, myFruit)) -- 1 

Bạn có thể sử dụng nó để tìm chìa khóa:

local fruits = { 
    apple = {color="red"}, 
    pear = {color="green"}, 
} 
local myFruit = fruits.apple 
local fruitName = table.find(fruits, myFruit) 
print(fruitName) -- "apple" 

Tôi hy vọng thông số recursive sẽ tự nói lên.

Thông số metatables cũng cho phép bạn tìm kiếm các thẻ meta.

Tham số keys làm cho hàm tìm kiếm các khóa trong danh sách. Tất nhiên đó sẽ là vô ích trong Lua (bạn chỉ có thể làm fruits[key]) nhưng cùng với recursivemetatables, nó trở nên tiện dụng.

Tham số returnBool là một an toàn-vệ cho khi bạn có các bảng có false như một chìa khóa trong một bảng (Có đó là có thể: fruits = {false="apple"})

Các vấn đề liên quan