lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Let me reiterate, changing the semantics of a table while using any
variant of pairs() is a bad idea.
if you count down from #table to 1 its fine.

Unless there is some real argument why "inplace" is bad, the best
solution is probably to do it exactly not inplace. Or use some other
construct, like chained lists where removals are cheap operations.

On Fri, Jan 14, 2011 at 8:58 AM, Robert G. Jakabosky
<bobby@sharedrealm.com> wrote:
> On Thursday 13, Axel Kittenberger wrote:
>> You must not change a table while iterating through it with
>> for/ipairs/pairs. While it might work with some reversal its still bad
>> style can possibly break.
>
> How can using a for loop counting down break?  Removing a node only effects
> the position of the nodes that where already processed.  The original
> question was for a "more elegant way" to solve the problem.
>
>> This will work instead:
>>
>> local tab = {"a", "a", "c", "a", "d", "a" }
>>
>> local len = #tab
>> local k = 1
>> while tab[k] do
>>     if tab[k] == "a" then
>>         table.remove(tab, k)
>>     else
>>         k = k + 1
>>     end
>> end
>>
>> for k, v in ipairs(tab) do print(k, v) end
>> print()
>> for k, v in pairs(tab) do print(k, v) end
>>
>>
>>
>> On Fri, Jan 14, 2011 at 5:26 AM, Robert G. Jakabosky
>>
>> <bobby@sharedrealm.com> wrote:
>> > On Thursday 13, Emmanuel Oga wrote:
>> >> Hello, I'm looking for the best proper way of doing this:
>> >>
>> >> local tab = {"a", "a", "c", "a", "d", "a" }
>> >>
>> >> for index, val in ipairs(tab) do
>> >>   if val == "a" then -- could be any other complex condition
>> >>     table.remove(tab, index)
>> >>   end
>> >> end
>> >>
>> >> -- WRONG: tab = { "a", "c", "d" }, should be { "c", "d" }
>> >>
>> >> So removing elements from a container _while you are iterating it_ is
>> >> wrong in most languages. I'm looking for the nicest and proper way of
>> >> doing it.
>> >>
>> >> Two methods I came up with:
>> >>
>> >> 1) popping from the array and pushing to a new one if the condition is
>> >> met. 2) Iterating first, storing indexes to remove, then removing one by
>> >> one (compensating index offset as a result of each removed elements)
>> >>
>> >> http://pastie.org/1458808
>> >>
>> >> Is there any other more elegant way?
>> >
>> > process the list in reverse.
>> >
>> > for index=#tab,1,-1 do
>> >  local var = tab[index]
>> >   if val == "a" then -- could be any other complex condition
>> >     table.remove(tab, index)
>> >   end
>> > end
>> >
>> >
>> > --
>> > Robert G. Jakabosky
>
>
>
> --
> Robert G. Jakabosky
>
>