[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: ipairs_remove - remove items from array while iterating it
- From: Hisham <h@...>
- Date: Mon, 4 Nov 2013 11:03:32 -0200
On 2 November 2013 15:27, Thijs Schreijer <thijs@thijsschreijer.nl> wrote:
>>
>> Well noted! Also including the fix by Ashwin Hirchi (I love this list!)
>>
>> local function ipairs_remove(tbl)
>> local i = 0
>> local shiftback = 0
>> local remove = function()
>> shiftback = shiftback + 1
>> i = i - 1
>> end
>> return function()
>> i = i + 1
>> if shiftback > 0 then
>> tbl[i] = tbl[i+shiftback]
>> end
>> if tbl[i] ~= nil then
>> return i, tbl[i], remove
>> end
>> for n = 1, shiftback-1 do
>> tbl[i+n] = nil
>> end
>> return nil
>> end
>> end
>>
>
> This contains some nasty side effects when not finishing the loop (return, break, or goto). Only when the loop finishes the remaining elements are cleared. So if you don't finish, they get duplicated. If you modify the code to clear them while looping, then breaking the loop results in a hole in the list (possibly even worse).
>
> So I think the remove() function should use table.remove() to clear the entry to prevent those sideeffects
This was a quick hack to see if I could make it linear and
forward-looping, but indeed, losing the ability to break is a deal
breaker for actual use (unintentional pun)... and for my application I
can handle the cost of table.remove() anyway.
> Having said that, I think the most elegant solution is backward traversal, as Pasi Mankinen already mentioned
I've always either used two loops (when I need to process them in
ascending order) or backward traversals, but never liked the
readability of the latter approach too much (when loops are a bit
larger it's never obvious that one is moving backwards just because it
may remove items).
-- Hisham