How do I remove values from an array with no gaps?
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.
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
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.
Good, because I wasn’t a big fan of creating a whole new table neither.
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 -->>
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 -->>
1 Marry
2 Roblox
Roblox table: 2D5492E4
Marry 5
--]]