lua-users home
lua-l archive

Re: Removing holes from a list

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


> 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

AltStyle によって変換されたページ (->オリジナル) /