【问题标题】:How to handle inserts and removes from a table and still know which entry is which?如何处理表中的插入和删除,并且仍然知道哪个条目是哪个条目?
【发布时间】:2012-01-17 04:21:10
【问题描述】:

我刚刚开始使用 Lua 进行冒险,但遇到了一些问题。

我有一个表,其中包含在我的应用程序中使用的对象实例。 我对每个条目都做了一些处理,完成后我想将其从表格中删除。

假设场景是这样的:

  • 创建 10 个实例并将它们插入表中

  • 对其中一些进行一些计算[随机选择]

  • 计算完成后,从表中删除条目

  • 同时向表中添加 10 个实例

  • 第 6 次计算后从表中删除所有条目

因为我知道从一开始就添加了多少对象,所以我使用这个计数作为条目的键:

table.insert(myTable, tostring(myObject.objectNumber), myObject)

我正在使用 tostring 来确保我不会遇到任何关键问题 [例如,count 从 0 开始]。

我想使用以下方法删除条目:

table.remove(myTable, tostring(myObject.objectNumber))

但这不是我必须作为第二个参数传递的键,而是表中的位置。这搞砸了整个想法,我对如何正确删除条目而不每次都在表格上进行循环有点迷茫。我看不到任何可以通过键为我提供条目的表格位置的功能。

编辑: 所以这个问题比我最初想的要大一点。 首先:

table.insert(myTable, tostring(0), "something")
assert #myTable == 0

我可以在我的日志中看到:

enemy count:    0
Inserting   0   table: 0x18e8a50
Insert check    0   table: 0x18e8a50
enemy count:    0
Inserting   1   table: 0x18c7c40
Insert check    1   table: 0x18c7c40
enemy count:    1

ipairs() 也不返回它。

我不知道为什么,但事实就是这样。

其次,

Inserting   0   table: 0x1781ac60
Insert check    0   table: 0x1781ac60
Inserting   1   table: 0x5e8c20      <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Insert check    1   table: 0x5e8c20 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Inserting   2   table: 0x17807390
Insert check    2   table: 0x17807390
Inserting   3   table: 0x5f5a30
Insert check    3   table: 0x5f5a30
Inserting   4   table: 0x18c7850
Insert check    4   table: 0x18c7850
Inserting   5   table: 0x5e15f0
Insert check    5   table: 0x5e15f0
Inserting   6   table: 0x1784c540
Insert check    6   table: 0x1784c540
Inserting   7   table: 0x5a7b80
Insert check    7   table: 0x5a7b80
Inserting   8   table: 0x18f6d30
Insert check    8   table: 0x18f6d30
Inserting   9   table: 0x189d3e0
Insert check    9   table: 0x189d3e0
remove  0   table: 0x1781ac60
remove check    0   nil 9
Inserting   10  table: 0x18e9c50
Insert check    10  table: 0x18e9c50
Inserting   11  table: 0x5d64a0
Insert check    11  table: 0x5d64a0
Inserting   12  table: 0x19d43540
Insert check    12  table: 0x19d43540
Inserting   13  table: 0x18d5730
Insert check    13  table: 0x18d5730
Inserting   14  table: 0x19d19110
Insert check    14  table: 0x19d19110
Inserting   15  table: 0x595800
Insert check    15  table: 0x595800
Inserting   16  table: 0x5e0f30
Insert check    16  table: 0x5e0f30
remove  5   table: 0x5e15f0
remove check    5   nil 16
remove  4   table: 0x18c7850
remove check    4   nil 16
remove  3   table: 0x5f5a30
remove check    3   nil 16
remove  2   table: 0x17807390
remove check    2   nil 16
remove  6   table: 0x1784c540
remove check    6   nil 16
remove  7   table: 0x5a7b80
remove check    7   nil 16
Inserting   17  table: 0x56fcf0
Insert check    17  table: 0x56fcf0
remove  1   table: 0x5e8c20 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
remove check    1   nil 17 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
remove  8   table: 0x18f6d30
remove check    8   nil 17
Inserting   18  table: 0x5970a0
Insert check    18  table: 0x5970a0
remove  9   table: 0x189d3e0
remove check    9   nil 18
Removing all entries:   
1   table: 0x5e8c20     <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2   table: 0x17807390
3   table: 0x5f5a30
4   table: 0x18c7850
5   table: 0x5e15f0
6   table: 0x1784c540
7   table: 0x5a7b80
8   table: 0x18f6d30
9   table: 0x189d3e0
10  table: 0x18e9c50
11  table: 0x5d64a0
12  table: 0x19d43540
13  table: 0x18d5730
14  table: 0x19d19110
15  table: 0x595800
16  table: 0x5e0f30
17  table: 0x56fcf0
18  table: 0x5970a0
remove  1   table: 0x5e8c20 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

如您所见,虽然我之前删除了该条目,但它似乎仍然存在。 现在..我认为这是表的全局局部变量问题,但我已将条目数添加到打印中[删除检查行中的最后一个条目]。 “删除所有条目”之后的列表是使用 for loop over pairs(myTable) 创建的。

这是我插入和删除条目的代码:

MyObject = {}
MyObject_mt = { __index = MyObject }

function MyObject:new(params)
    MyObject = {
        objectNumber = params.objectNumber
    }
    local myObject = setmetatable(MyObject, MyObject_mt)

    print("Inserting", tostring(myObject.objectNumber), tostring(myObject))
    table.insert(myTable, tostring(myObject.objectNumber), myObject)
    print("Insert check", tostring(myObject.objectNumber), tostring(myObject))

    function MyObject:removeObject(event)
        print("remove", self.objectNumber, tostring(self))
        myTable[tostring(self.objectNumber)] = nil
        print("remove check", self.objectNumber, tostring(myTable[self.objectNumber]), #myTable)
        end
    end

    return myObject
end

【问题讨论】:

  • 直接使用整数 (myObject.objectNumber) 作为索引,而不是 tostring() 方法。这将使字典脱离应该是一个数组,然后麻烦就开始了(ipairs not working # not working 等)。但是,还要记住 # 不适用于其中有孔的数组。
  • 我可以没有#,但是我不能使用一些整数作为键,它们可以在我的代码中使用。 0 就是其中的一个例子。我可能会得到一个负数。这就是我选择使用 tostring 的原因。这就是为什么我正在寻找另一种方法来将条目插入表中并[确定]它是键/位置 - 即无需预先指定一个。

标签: lua


【解决方案1】:

假设您没有连续的对象编号(即不要将表用作数组而是用作字典),您可以简单地做一个

table[tostring(myObject.objectNumber)] = nil;

就是这样,条目已删除。

【讨论】:

  • 但是这种方法的问题是#myTable 不会改变。我需要知道有多少条目。
  • 对于字典来说,# 运算符根本不适用。而且,如果您将表用作数组,则通过为 table.remove() 提供正确的索引已经做得很好了-所以我在这里并没有真正遇到问题...
  • 我已经编辑了我的问题以添加示例和一些调试打印输出以及代码。
  • 好吧,我听从了您的建议,创建了一个单独的注册表来计算添加的对象,并使用单独的序列作为键。现在它工作正常。谢谢!
猜你喜欢
  • 1970-01-01
  • 2016-07-10
  • 2018-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-05
相关资源
最近更新 更多