[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Removing holes from a list
- From: "Gary V. Vaughan" <gary@...>
- Date: Sun, 27 Sep 2015 14:21:29 +0100
> On 26 Sep 2015, at 19:58, Dirk Laurie <dirk.laurie@gmail.com> wrote:
>
> 2015-09-26 17:44 GMT+02:00 Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>:
>>
>> Try this:
>>
>> list=table.pack(1,2,3,nil,4,5,nil,nil,6,7)
>>
>> local n=0
>> for i=1,list.n do
>> if list[i]~=ni then
>> n=n+1
>> list[n]=list[i]
>> end
>> end
>> list.n=n
>>
>> for k,v in ipairs(list) do print(k,v) end
>
> This is a little like one of my solutions, but neater. Thanks.
>
> However, #list is still 10. One needs, before resetting list.n,
>
> for i=n+1,list.n do list[i]=nil end
>
Here’s a (non-destructive) functional solution:
function id (...) return ... end
function collect (r, predicate, n, x, ...)
if n == 0 then return r end
r[#r + 1] = predicate (x) and x or nil
return collect (r, predicate, n - 1, ...)
end
function filter (predicate, ...)
return collect ({}, predicate, select ("#", ...), ...)
end
r = filter (id, 1, 2, 3, nil, 4, 5, nil, nil, 6, 7)
or, if you prefer:
r = filter (id, (table.unpack or unpack) (list))
Thanks to tail-call elimination it’s actually reasonably fast too.
The slow `r[#r + 1]` part could be mitigated with a (premature! ugly!) optimisation:
function collect (r, i, predicate, n, x, ...)
if n == 0 then return r end
if predicate (x) then
i = i + 1
r[i] = x
end
return collect (r, i, predicate, n - 1, ...)
end
function filter (predicate, ...)
return collect ({}, 0, predicate, select (“#”, ...) ...)
end
But it all boils down to keeping track of two indices, n and i, in any case :)
Cheers,
Gary