How to Remove All Nil Values From a Table And Shift Values Down?

I’ve tried doing a bit of Google search and DevForum search, but all I can find are the basic functions like table.remove and table.clear.

Let’s say I have a table like this one:

local fruits = {"Apple", nil, "Banana", nil, "Lemon", nil, "Grape"}

Is there a quick and easy way to get rid of all the nil values and shift everything down to make it look like this?

local fruits = {"Apple", "Banana", "Lemon", "Grape"}

There’s probably some way to code this by just looping through the table and removing nil values and shifting down the strings until there are none left, but I’d love to avoid that if possible as this is something I’ll be calling repeatedly for my script. Thanks in advance!

1 Like
for i = 1, #fruits do
    if fruits[i] == nil then
        table.remove(fruits, i)
    end
end

dont really see another way to do this

2 Likes

you can create a function to make it easier.

function removeNils(tab) for i = 1,#myArray do if myArray[i] == nil then table.remove(myArray, i) end end end
removeNils(myArray)

Those won’t work because # ignores nils because you’re iterating in order while using table.remove. :/

local function unsparse(array)
    local highestIndex = 0
    local numElements = 0

    -- Need to use pairs, as both ipairs and # stop at nil
    -- pairs has an undefined iteration order so collect the maximum index to iterate to later
    for k in pairs(array) do
        -- Positive integral indices
        if type(k) == 'number' and k > 0 and k % 1 == 0 then
            highestIndex = math.max(highestIndex, k)
            numElements += 1
        end
    end

    local result = table.create(numElements)
    local resultN = 0

    for i = 1, highestIndex do
        local val = rawget(array, i)

        if val ~= nil then
            -- Faster than table.insert because we cache resultN
            resultN += 1
            result[resultN] = val
        end
    end

    return result
end
5 Likes

I tried mine and it works apparently

It doesn’t, at the very least you would need to do:

for i = #myArray, 1, -1 do
    if myArray[i] == nil then
        table.remove(myArray, i)
    end
end

because otherwise you would skip over multiple nils in sequence, because table.remove would shift them backwards. in other words 1, 2, 3, nil, nil, 4 would become 1, 2, 3, nil, 4 instead of 1, 2, 3, 4

9 Likes