Add table.removeValue

I very frequently use the 4 lines of code below in my game and I think it is common usage for the table.find function, so adding a table.removeValue function would be convenient and maybe more efficient since there would be no Index variable

--Old
local Index = table.find(Table, Value)
if (Index) then
    table.remove(Table, Index)
end

--New
table.removeValue(Table, Value)

--table.find was added to replace these 4 lines of code so table.removeValue isn't bloat
local Value = "a"
for Index, CheckValue in pairs(Table) do
    if (CheckValue == Value) then return Index end
end
3 Likes

Lua’s table remove is very similar to just doing
table[index] = nil. However, it will shift keys above it if they’re in a numeric sequence

A removeValue function adds unnecessary bloat to the Lua VM as Lua does not natively have the .find function

If you seriously want to remove by value in a table…

function removeValue(t, v)
  table.remove(t, table.find(t,v))
end

However this will only only work on numeric arrays and in Luau

3 Likes

A lot of other programming languages like Java have a remove function which will remove the first instance of a given value, however this is usually when languages are more strict on data types and allow overloading of functions.

That said, a quick test seems to show that table.remove has no effect (without raising an error) if the 2nd parameter is nil, so you may as well just do:

~table.remove(t, table.find(t, v))

Ignore that, I was only testing on the 2nd element. @wallythecocatoo, who can’t post, informs me that it removes the last value.

I’d actually like to see remove work with dictionaries too. That would be very convenient!

(Also, I’d just like to mention a correction from @avozzo, table.remove additionally shifts the array over. I’ve updated the post)

Personally, I can’t think of this being particularly beneficial in many places, but, that may just be because of how I tend to structure my tables and just my habits in general. I would, however, definitely love to see table.remove receive support for dictionaries, because I found it (and still do find it) confusing that table.remove only works for arrays. For a good while, I assumed there was no way to do this for dictionaries, until I learned, that really all that table.remove does is to set the entry in the table to nil and shift the table over.

table.remove functionally looks like this although its likely faster than this would end up being:

function table.remove(tab, index)
	assert(typeof(tab) == "table", "Some error message.")
	assert(typeof(index) == "number", "Some error message.")
	if index == nil then
		index = #tab
	end
	
	local existingValue = tab[index]
	if existingValue ~= nil then
		rawset(tab, index, nil)
		table.move(tab, index+1, #tab, index)
	end
	
	return existingValue
end

Generally, this is what I tend to do, and, this is a big reason why I don’t see this being a useful addition, although, again, this is maybe just personal.

When I need to remove a value from a table, generally when I have a lot of values to remove, I mark value indexes within the table like so:

tab[index] = value
tab[value] = index

Then to delete the entry I do the following:

local index = tab[value]
tab[index] = nil
tab[value] = nil

And in the case where I may possibly add duplicate entries I just use the following before:

local oldIndex = tab[value]
if oldIndex and tab[oldIndex] ~= nil then
	tab[oldIndex] = nil -- Clear the index entry
end

This also couples well with the __mode metamethod (Which also acts as an alternative to the above, and is what I tend to use, although I combine both):

setmetatable(tab, {
	__mode = "k" -- Make keys weak. This doesn't effect the actual array entries, but, the value to index entries will be weak meaning they will GC on their own.
})

This gets a good bit more off topic from the feature request, but, its related to the topic of tables & convenience.
I remember seeing something about the consideration of Roblox adding a StringBuilder class (unfortunately I couldn’t find where I ended up seeing this mentioned) to give a more official method of concatenating lots of text quickly. (As for why a StringBuilder object might be added, in practice concatenating lots of items normally showed to be nearly 600x slower on my hardware which was enough to prompt me to make the linked post)

I personally think that maybe tables in Roblox should get their own specialized custom class (not as a replacement, but really just for convenience), just like Instances, Vector3s, or whatever which would mimic the structure of whatever StringBuilder implementation might happen.

The reason I think a custom object might help is because it allows for diverging from being “lua-like.” table comes from vanilla lua, and is usually meant to be compatible with different vanilla lua versions. Because of this, usually most of these features that I’ve seen added come from newer lua versions.

This is close to really being a second feature request, but, I am sort of curious on whether or not some sort of “helper” would end up being an acceptable solution to a lot of the littler issues with the table library such as this. I’m not sure, maybe this is a bit too over the top.