Remove from table while iterating

Normally, removing an item from a container (like the table in lua) while iterating over it is bad - I’ve just tried it and it seems to work. Am I asking for trouble? Should I do the remove after iterating?


You are asking for trouble, the behaviour if you do that is undefined. You could either remove after the iteration, or just copy the stuff you want to keep to a new table and continue to use that. Much cleaner IMO.

Well, normally removing from an array while iterating is bad. Tables aren’t exactly arrays, but can be treated as such. Without experimenting, I can’t say for sure why would happen of the underlying table is structured as an array, but I’ll bet that of you are iterating using pairs instead of ipairs (treating the table more like a map or a dictionary) that it would probably be okay to remove items while iterating. Hopefully someone with more expertise can give a more definitive answer. I worry that just because you didn’t have any problems in your case, it doesn’t mean in other cases (or if your situation was slightly changed up) there won’t be a problem.

Thanks - yes I think it’s too dangerous to rely on, I expect they may be linked lists but for sure the best thing is to remove separately. I raise the topic as it’s a classic and easy error to make - like I say, it may appear to work, but what is actually getting corrupted under the covers, who knows.

Well, Lua provides 2 ways of implementing tables depending on how you use them: either as a traditional array (with all objects packed together in memory and accessed via an array index), or as an associative array (key-value pairs in which the objects are accessed via their key, but objects are stored on an arbitrary manner…like std::map or a dictionary). I’m googling around to see what more I can dig up though on the safety of removing objects from a table while iterating. I suspect that it’s dangerous, but I’d like to understand a little better how this works under the hood.

From a cursory search, the only way it appears to be safe to do this is a) use pairs and not ipairs to iterate, b) set the value to nil instead of using table.remove(), and c) don’t add objects to the table while iterating, so the iterators don’t get confused. Honestly, I doubt I would ever go this route, because it seems error prone and brittle. @gunnar_z’s suggestions are definitely the way to go, and the way I would likely do it.