lua-users home
lua-l archive

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


2013/11/2 Philipp Janda <siffiejoe@gmx.net>:

> Maybe a for loop iterator is the wrong interface for this particular
> problem. Maybe something like `table.foreachi_rm()`?
> Or the "second loop" method in form of a `compact()` function ...
>
>     local n = #t
>     for i = 1, n do
>       if should_remove( t[ i ] ) then t[ i ] = nil end
>     end
>     compact( t, n )   -- or compact( t, 1, n )

Microlight has 'ifilter'.

--- filter a array using a predicate.
-- If `pred` is absent, then we provide a default which
-- filters out any `false` values.
-- @param t a table
-- @param pred the predicate function
-- @param ... any extra arguments to the predicate
-- @return a array such that `pred(t[i])` is true

$ lua -l ml

> t = { "a", "b", "c", "d", "e" }
> print(ml.tstring(ml.ifilter(t, function(x) return x~='c' end )))
{"a","b","d","e"}

The code (some Microlight idiosyncrasies removed) is very
straightforward:

function ifilter(t,pred,...)
    local res,k = setmetatable({},getmetatable(t)), 1
    pred = pred or true
    for i = 1,#t do
        if pred(t[i],...) then
            res[k] = t[i]
            k = k + 1
        end
    end
    return res
end


This is O(n) and does not destroy the original table.
You can do that yourself by assigning the result of
ifilter to it.