Removing Value From Array With No Gaps

How do I remove values from an array with no gaps?

1 Like

If you know the index of the item you want to remove, you can use table.remove(table, index). This automatically shifts down all other items. But only works if your indexes are numerical.

1 Like

But what if theres multiple of that index? Then it won’t guarantee to get all of them.

Indexes are unique. If you’re talking about values, those are not guarenteed to be unique (on it’s own).

local function removeValuesFromArray(array, value)
	for i = #array, 1, -1 do
		if array[i] == value then
			table.remove(array, i)
		end
	end
end

local myArray = {1, 6, 2, 8, 4, 8, 3, 8, 2}
removeValuesFromArray(myArray, 8)
print(table.concat(myArray, ", ")) --> 1, 6, 2, 4, 3, 2
14 Likes

Yeah, im talking about values.

The only way i can see as a solution is iterating thru all of them and setting them to nil and then doing another loop to input it into a new table to remove the gaps

If your list of values is small, or if you’re not running the search that often, then that method is just fine.

Edit: didn’t read your last post carefully. table.remove won’t create any gaps or anything—it closes the “gap” when it removes an element, so you don’t have to worry about the table having gaps or anything. Osyris’s method should work fine.

This may be a xy problem, if you disagree please tell me. I’m not trying to answer the question, but to solve a possible problem you’re experiencing.
If the order of the values doesn’t matter, you should better go off with dictionaries. Since there can only be one key per value, you could map the data of your array as keys, take this example from wiki:

local playerScores = {
	[game.Players.Telamon] = "Over 9000!",  
	[game.Players.Roblox] = 1337,
	[game.Players.Sorcus] = Enum.DialogTone.Enemy
}

You don’t need to iterate over the table to check if Roblox already has a score, because it’s being used as a key. We can better help you if you tell us why you would want to remove values from arrays without “gaps”.

What happens if it’s a large table and you dont wanna any gaps and you dont want to use table remove?

since using table.remove can shift the list down and skipping some elements that should be removed when iterating thru all at once

In that case, if the order of the elements doesn’t matter, you could do the following: swap the deleted element with the last value in the table, then call table.remove(t) without passing an index, which deletes the last value. That way you won’t have to shift all the elements.

That wouldn’t work because, what happens if the last value of the table also needs to be removed. Swapping it would skip it over.

For example, trying to remove “1” from the a table:

local function QuickRemove(tbl, index)
	local size = #tbl
	tbl[index] = tbl[size]
	tbl[size] = nil
end

local Table = {1, 1, 7, 3, 2, 1}

for i, v in pairs(Table) do
	if v == 1 then
		QuickRemove(Table,i)
	end
end

print(table.concat(Table, ", ")) --> 1, 2, 7, 3

Then you can just check if i == #Table-1, in which case you just call table.remove(Table).
Or, even better, iterate from 1 to #Table-1, then leave the last element as an edge case.

EDIT: Actually, you’re right, it’s not quite as simple as I laid it out. It’s still fairly simple, though.

Here’s my implementation:

local t = {1,1,7,3,2,1}
local Value = 1
do
    local i,n = 1,#t
    local remove = table.remove
    while i<n do
        while t[i]==Value do
            t[i]= t[n]
            remove(t)
            n = n-1
        end
        i = i+1
    end
    print(table.concat(t,', '))
end

The only way i can see as a solution is iterating thru all of them and setting them to nil and then doing another loop to input it into a new table to remove the gaps -Earlier Post

Which way would be more efficient for large tables, yours or mine? Both ways requires iterating thru all the values tho.

All I wanted to show is that you don’t have to create a new table to do what you’re asking. It can all be done in-place.

I don’t think you can get much faster than the code I posted, unless you store the data differently (e.g. a LinkedList). But then you have to make tradeoffs for things like indexing time and memory usage, which arrays are great at doing.

1 Like

Good, because I wasn’t a big fan of creating a whole new table neither. :stuck_out_tongue:

this works too:

local Table = = {1,1,7,3,2,1}
local i = 1

while i <= #Table do
    if Table[i] == 1 then
        table.remove(Table, i)
    else
        i = i + 1
    end
end

print(table.concat(Table, ", "))

Similar to yours.

I thought we just established that table.remove(t,i) would be inefficient, since it shifts all the elements. That will make it run much much slower.

Although, unless you’re dealing with arrays of 1000 elements or more on a frame-by-frame basis, the increase in speed probably won’t matter.

Don’t forget to add a wait for your PC might Explode!!


You can Mix an Array with a Dictionary, the only draw back is that you can’t send the Full Table with a RemoteObj but you can just Separate the Table and then Re-Combine them later so it’s just Extra work.

local Array_Dictionary = {

'Johny',

Johny = true,

'Marry',

['Marry'] = 5,

}

Array_Dictionary[3] = 'Roblox'

Array_Dictionary.Roblox = {}

for i , v in pairs(Array_Dictionary) do

print(i,v)

end

--[[

Output --&gt;&gt;

1 Johny

2 Marry

3 Roblox

Roblox table: 2E12F52C

Johny true

Marry 5

--]]

Array_Dictionary[Array_Dictionary[1]] = nil

table.remove(Array_Dictionary,1)

for i , v in pairs(Array_Dictionary) do

print(i,v)

end

--[[

Output --&gt;&gt;

1 Marry

2 Roblox

Roblox table: 2D5492E4

Marry 5

--]]

A Lesson About Tables