【问题标题】:How to search Lua table values如何搜索 Lua 表值
【发布时间】:2022-04-30 05:44:56
【问题描述】:

我有一个项目需要在实际数据库不可能的环境中使用类似结构的关系数据库。该语言仅限于 Lua,这远非我最强的语言。我有一张表,其结构如下:

table={
  m:r={
    x=1
    y=1
    displayName="Red"
  }
  m:y={
    x=1
    y=2
    displayName="Yellow"
  }
}

构建、存储和检索表非常简单。我遇到问题的地方是搜索它。为了清楚起见,如果我可以使用 SQL,我会这样做:

SELECT * FROM table WHERE displayName="Red"

是否有一个 Lua 函数可以让我以这种方式搜索?

【问题讨论】:

  • 您必须遍历表格。

标签: search lua lua-table


【解决方案1】:

直接的方法是遍历所有元素并找到符合您条件的元素:

local t={
  r={
    x=1,
    y=1,
    displayName="Red",
  },
  y={
    x=1,
    y=2,
    displayName="Yellow",
  },
}
for key, value in pairs(t) do
  if value.displayName == 'Red' then
    print(key)
  end
end

这应该打印'r'。

这在大桌子上可能会很慢。为了加快此过程,您可以跟踪 hash 中的引用,这将提供更快的访问速度。这样的事情可能会奏效:

local cache = {}

local function findValue(key)
  if cache[key] == nil then
    local value
    -- do a linear search iterating through table elements searching for 'key'
    -- store the result if found
    cache[key] = value
  end
  return cache[key]
end

如果表中的元素更改了它们的值,则需要在更新或删除值时使缓存无效。

【讨论】:

    【解决方案2】:

    没有用于搜索表格的内置函数。有很多方法可以解决它,它们的复杂性和效率各不相同。

    local t = {
      r={displayname="Red", name="Ruby", age=15, x=4, y=10},
      y={displayname="Blue", name="Trey", age=22, x=3, y=2},
      t={displayname="Red", name="Jack", age=20, x=2, y=3},
      h={displayname="Red", name="Tim", age=25, x=2, y=33},
      v={displayname="Blue", name="Bonny", age=10, x=2, y=0}
    }
    

    Programming in Lua 中,他们建议构建一个反向表以进行高效查找。

     revDisplayName = {}
     for k,v in pairs(t) do
          if revDisplayName[v.displayname] then
              table.insert(revDisplayName[v.displayname], k)
          else
             revDisplayName[v] = {k}
          end
     end 
    

    然后您可以轻松匹配显示名称

    for _, rowname in pairs(revDisplayName["Red"]) do
       print(t[rowname].x, t[rowname].y)
    end
    

    如果您想构建复杂的查询,可以在 Lua、Lua 表、Beginning Lua Programming 中创建类似 SQL 的查询的代码。

    如果您只想在几条记录中搜索匹配项,您可以使用 iterator in Lua 抽象搜索

    function allmatching(tbl, kvs)
      return function(t, key)
        repeat
          key, row = next(t, key)
          if key == nil then
            return
          end
          for k, v in pairs(kvs) do
            if row[k] ~= v then
              row = nil
              break
            end
          end
        until row ~= nil
        return key, row
      end, tbl, nil
    end
    

    你可以这样使用:

    for k, row in allmatching(t, {displayname="Red", x=2}) do
      print(k, row.name, row.x, row.y)
    end
    

    打印出来的

    h   Tim     2   33
    t   Jack    2   3
    

    【讨论】:

      猜你喜欢
      • 2013-05-22
      • 1970-01-01
      • 2021-02-17
      • 1970-01-01
      • 1970-01-01
      • 2017-04-04
      • 2019-08-28
      • 2015-07-28
      • 1970-01-01
      相关资源
      最近更新 更多