如何搜索Lua表中的值

我有一个项目需要在实际数据库不可能的环境中实现类似关系型数据库的结构。这个项目只能使用Lua这种编程语言,而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函数能够让我这样搜索?

点赞
用户1442917
用户1442917

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

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'。

在大型表上,这可能会很慢。为了加快这个过程,您可以在一个哈希表中跟踪引用,这将提供更快的访问速度。下面的代码可能有效:

local cache = {}

local function findValue(key)
  if cache[key] == nil then
    local value
    -- 做一个线性搜索,遍历表中的元素搜索 'key'
    -- 如果找到了,存储结果
    cache[key] = value
  end
  return cache[key]
end

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

2014-11-14 21:54:50
用户2726734
用户2726734

没有内置函数用于搜索表格。有多种方法可以完成,这些方法在复杂度和效率上也有所不同。

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}
}

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 表格使用类似 SQL 的查询代码,如 Lua 编程入门 中的代码。

如果你只想为匹配搜索几条记录,你可以使用 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
2014-11-15 17:17:07