循环直到在表中找到2个特定值?

时间:2014-12-13 20:04:51

标签: loops search for-loop lua

我试图找到一种更聪明的方法来解决这个问题。

这是与游戏相关的代码的摘录,它循环通过每个背包的每个插槽,直到它找到一把铲子和一根绳子

local continue
local foundShovel, foundRope
        for i = 0, Container.GetLast():Index() do -- looping trough backpacks
        local cont = Container(i)
            for j = 0, cont:ItemCount()-1 do -- looping trough each slot
            local id = cont:GetItemData(j).id -- Getting ID of that slot
            foundShovel, foundRope = GetToolIndex(id,0) or foundShovel,GetToolIndex(id,1) or foundRope -- confusing...
                if foundShovel and foundRope then
                    continue = true
                    break
                end
            end
            if continue then
               -- do something i need to do
            end
        end
    end
-- Switches ID to corresponding index :
function GetToolIndex(id,retrn)
    local shovel = {
    [9598] = 4 , -- whacking driller of fate
    [9599]= 4 , -- whacking driller of fate(jammed)
    [9596]= 3 , -- squeezing gear of girlpower
    [9597]= 3 , -- squeezing gear of girlpower(jammed)
    [9594]= 2 , -- sneaky stabber of elitenesss
    [9595]= 2 , -- sneaky stabber of elitenesss(jammed)
    [5710]= 1, -- light shovel
    [3457] = 0 -- shovel
    }
    local rope = {
    [646]= 1, -- elvenhair rope
    [3003] = 0, -- rope
    [9598] = 4 , -- whacking driller of fate
    [9599]= 4 , -- whacking driller of fate(jammed)
    [9596]= 3 , -- squeezing gear of girlpower
    [9597]= 3 , -- squeezing gear of girlpower(jammed)
    [9594]= 2 , -- sneaky stabber of elitenesss
    [9595]= 2  -- sneaky stabber of elitenesss(jammed)
    }
    if retrn == 0 then 
        return shovel[id] 
    elseif return == 1 then 
        retrn rope[id] 
    end
end

但它不起作用,我认为这种方法必须有更好的方法,如果我需要在一个表中找到X值而不是仅仅2?我希望我的问题可以在这里理解。

1 个答案:

答案 0 :(得分:3)

好吧,将所有数据存储在表中要好得多,而不是调用函数来获取容器数据。

无论如何这里有一个脚本可以获取所有背包ID,将它们存储在一个表中,然后只需用每个id调用你的函数。

Backpack = {data = {}};
function Backpack:update(refresh)
    if(#self.data==0 or refresh) then
        for i = 0, Container.GetLast():Index() do
            local cont = Container(i);
            for j = 0,cont:ItemCount()-1 do
                --table.insert(self.data,cont:GetItemData(j).id)
                self.data[#self.data+1] = cont:GetItemData(j).id; -- faster than table.insert
            end
        end
    end
end
function Backpack:refresh()
    self:update(true)
end
function Backpack:find(func,...) -- func should return a value if id is good, otherwise false, add extra args to call with the function
    if (not func) then
        return false;
    end
    self:update(); -- Incase there is no inventory data;
    for key,value in pairs(self.data) do
        local value = func(value,...); -- calls the function with the id (as first parameter) of the 'cached' user inventory
        if (value) then
            return value
        end
    end
    return false;
end

示例:

function GetToolIndex(id,return)
    local shovel = {
    [9598] = 4 , -- whacking driller of fate
    [9599]= 4 , -- whacking driller of fate(jammed)
    [9596]= 3 , -- squeezing gear of girlpower
    [9597]= 3 , -- squeezing gear of girlpower(jammed)
    [9594]= 2 , -- sneaky stabber of elitenesss
    [9595]= 2 , -- sneaky stabber of elitenesss(jammed)
    [5710]= 1, -- light shovel
    [3457] = 0 -- shovel
    }
    local rope = {
    [646]= 1, -- elvenhair rope
    [3003] = 0, -- rope
    [9598] = 4 , -- whacking driller of fate
    [9599]= 4 , -- whacking driller of fate(jammed)
    [9596]= 3 , -- squeezing gear of girlpower
    [9597]= 3 , -- squeezing gear of girlpower(jammed)
    [9594]= 2 , -- sneaky stabber of elitenesss
    [9595]= 2  -- sneaky stabber of elitenesss(jammed)
    }
    if return == 0 then 
        return shovel[id] 
    elseif return == 1 then 
        return rope[id] 
    end
end

function Test()
    local shovel,rope = Backpack:find(GetToolIndex,0),Backpack:find(GetToolIndex,1)
    if (shovel and rope) then
        print("Shovel and rope exist");
    end
end
Test();

修改

经过一段时间的考虑,您似乎试图检查用户是否具有该特定ID。

这里有另一种方法,即将检查所有用户背包数据(深层表搜索),它将根据表键或表值进行搜索,它也可以在嵌套表上工作,这应该对你有好处。

Backpack = {data = {}};
function Backpack:update(refresh) 
    if(#self.data==0 or refresh) then
        for i = 0, Container.GetLast():Index() do
            local cont = Container(i);
            for j = 0,cont:ItemCount()-1 do
                local data = cont:GetItemData(j); -- pretty sure this returns a table
                self.data[data.id] = data; -- self.data[9598] = {...}
            end
        end
    end
end
function Backpack:refresh()
    self:update(true)
end
function Backpack:MultiTableSearch(input,value,case,index_check)
    if (input and type(input) == 'table') then
        if (type(value) == 'table' and value == input) then
            return true;
        end
        for key,object in pairs(input) do
            if (index_check) then
                if (case and type(input)=='string' and type(key)=='string') then
                    if (value:lower() == key:lower()) then -- to avoid exit the loop
                        return true;
                    end
                else
                    if (key == value) then
                        return true
                    elseif(type(object)=='table') then
                        return self:MultiTableSearch(object,value,case,index_check)
                    end
                end
            else
                if (case and type(value)=='string' and type(object) == 'string') then
                    if (value:lower() == object:lower()) then
                        return true;
                    end
                elseif(type(object)=='table') then
                    if (value == object) then
                        return true;
                    else
                        return self:MultiTableSearch(object,value,case)
                    end
                else
                    if (object == value) then
                        return true;
                    end
                end
            end
        end
    end
    return false;
end
function Backpack:exists(value,case,index_check)
    self:update();
    return self:MultiTableSearch(self.data,value,case,index_check)
end
 -- checks the value 9598, case-insensitive is set to false,
 -- index_checking is set to true (checks table index --> Backpack.data[9598], if it was set it'll return true);
if (Backpack:exists(9598,false,true)) then
    print("User has whacking driller of fate");
end
if (Backpack:exists("Shovel of doom")) then -- will try to find any table-value that has the of "Shovel of doom" (case-sensitive)
    print("User Shovel of doom");
end

如果您担心MultiTableSearch的性能(因为它看起来有点沉重),它的速度非常快,可以进行多次测试。

功能

function MultiTableSearch(input,value,case,index_check)
    if (input and type(input) == 'table') then
        if (type(value) == 'table' and value == input) then
            return true;
        end
        for key,object in pairs(input) do
            if (index_check) then
                if (case and type(input)=='string' and type(key)=='string') then
                    if (value:lower() == key:lower()) then -- to avoid exit the loop
                        return true;
                    end
                else
                    if (key == value) then
                        return true
                    elseif(type(object)=='table') then
                        return MultiTableSearch(object,value,case,index_check)
                    end
                end
            else
                if (case and type(value)=='string' and type(object) == 'string') then
                    if (value:lower() == object:lower()) then
                        return true;
                    end
                elseif(type(object)=='table') then
                    if (value == object) then
                        return true;
                    else
                        return MultiTableSearch(object,value,case)
                    end
                else
                    if (object == value) then
                        return true;
                    end
                end
            end
        end
    end
    return false;
end

测试(将值附加到表中并扫描嵌套表,两个测试都是无意义的表大小)

local start_time = os.clock();
t = {}
for i=1,500000 do --500k table size
    t[i]=i-1
end
print(os.clock()-start_time) -- 0.05 sec to create the table
local start_time = os.clock();
print(tostring(MultiTableSearch(t,500000,false)))-- will try to find a key with the value of 500,000
print(os.clock()-start_time) -- 0.197sec sec to scan the whole table

function nestedTable(object,times) -- creates nested table -> object={{{{..n times}}}}
    if (times > 0 ) then
        object[#object+1] = {times = times}
        return (nestedTable(object[#object],times-1))
    end
end
local start_time = os.clock();
t = {};
nestedTable(t,15000) --> will create table inside a table x 15000 times.
print(os.clock()-start_time) -- 0.007 sec to create the nested table
local start_time = os.clock();
print(tostring(MultiTableSearch(t,1,false)))-- will try to find a 1 (as a table value), the very last table value
print(os.clock()-start_time) -- 0.014 sec to find the value in the nested table