以非整数键名来移除表中元素

我想实现一个能够删除满足给定判断条件的元素的 removeIf(aTable, unaryPredicate) 函数。

我凭感觉写出了以下代码,令我惊讶的是它居然可以正常工作:

for k, v in pairs(aTable) do
    if unaryPredicate(v) then
        atable[k] = nil
    end
end

对于 nextpairs 让这段代码能够正常工作的魔法力量是什么?就我所知,它会遍历整个 aTable,遍历次数恰好为 aTable 的大小。

点赞
用户107090
用户107090

next 仅依赖于表中的键。循环会移除值但不会移除键(在当前的 Lua 实现中)。文档明确说明您可以像您的循环一样从表中移除值。它还指出,您不能使用新键添加新条目,这正好会使 next 困惑。

2018-09-26 12:14:53
用户2616735
用户2616735

Lua表实际上是哈希表实现的。哈希表存储一个(key,value)对的数组。

**next**使用哈希快速跳到表中应该存在的键。

然而,需要注意的是,在next实现中有一个nil检查:

if (!ttisnil(&t->array[i])) { /* a non-nil value? */             

这是因为当将nil分配给表的键时,它会更新哈希表中的(key,value)对,但实际上并不会删除该条目。因此,您会在哈希表中留下一个(key,nil)条目。这个设计允许迭代通过next继续进行,即使当给现有键分配值,包括分配给nil时也是如此。

然而,这是一个_实现细节_。表是否有空值条目在表实现所暴露的API中是完全不可见的。每个外部函数都以完全相同的方式处理这些nil键,就像它们不存在一样。

2018-09-26 14:06:16