What is the most efficient and direct way to remove something from a table?

I’m having a little problem here trying to get my code to work as efficiently as I can. I posted a few days ago here about a similar issue and that post was helpful, but now I want to see if there are any better ways to accomplish what I am trying to accomplish.

local MyDataTable = {"Number 1","Position 2","Index 3","So on and so forth 4"}

function SearchAndRemoveSomethingFromMyDataTable(StringIWantRemoved)
	for i,v in pairs(MyDataTable) do
		if v == StringIWantRemoved then
			table.insert(MyDataTable,2,"Test") -- this is used to simulate something being added to the table before this loop is completed.
			print(MyDataTable[2]) -- printing here results in "Test" output
			table.remove(MyDataTable,i) -- this removes the "Test" input rather than the desired string I wished to remove.
			break
		end
	end
end

SearchAndRemoveSomethingFromMyDataTable("Position 2")


print(unpack(MyDataTable)) -- this prints MyDataTable exactly as seen at the top, with "Position 2" still inside of it.

This is the method I use to search a table, find what I want, and either do something with it or remove it. In the example, before the “Position 2” string gets removed, something is added to the table in the position 2 index. Instead of removing the desired string, the new input is removed instead. Obviously that is not desirable. Am I doing something wrong? Is there a better way to do this?

1 Like

I think the best way of doing that is just replacing your old index with your new string:

MyDataTable[2] = "Test"

The other way of doing it is removing from the table first and inserting afterwards:

table.remove(MyDataTable, i)
print(MyDataTable[2]) --> Index 3
table.insert(MyDataTable, 2, "Test")

Hopefully that helps.

1 Like

I’m not actually trying to insert Test into the table, that is just the device I’m using to simulate something being added. I’m using a module script to store data for all the players in the server, and when those players leave I want their respective data to be removed from the table. If, in the process of searching for their data, someone were to join and their data was added, there is the potential for something like this to occur. I’m trying to solve that potential issue.

Sorry, just realized you were removing it in the wrong order, ignore my comment above. As goldenstein64 stated above, you can just simply

for i,v in pairs(MyDataTable) do
  if v == StringIWantRemoved then
    MyDataTable[i] = "Test";
    break;
  end
end

Just in case you didnt see my reply from earlier in the thread.

Why try to add it at that specific location tho, why not let the table shrink via table.remove(), and then table.insert() when a new player joins?

It’s probably better to use a dictionary instead of an array then:

local AllData = {}

function OnPlayerAdded(plr)
    local data = -- get data table

    AllData[plr.UserId] = data
end

function OnPlayerRemoving(plr)
    AllData[plr.UserId] = nil
end

You can then access data like so:

local plrData = AllData[plr.UserId]
3 Likes

I’m not sure if this is answering your question but:

There are two ways of removing something, either through

table.remove

or making the value nil inside the table

MyDataTable[2] = nil

The difference between the both is that table.remove completely removes it but the indexing method just removes the value.

This forum post is also useful to understand the comparisons

This is what I wanted. Didn’t know this was a thing. Thank you.

3 Likes

What? Elaborate on this, it’s vague.

The actual difference between table.remove and value niling is that table.remove will also move all the values back 1 slot after the one you removed, and niling will leave these values intact.

2 Likes

Adding onto this, dictionaries are in general a really efficient way to do sets:

local infectedPlayers = {} 

local function infect(player)
    infectedPlayers[player] = true
end

local function heal(player) 
    infectedPlayers[player] = nil
end

local function isInfected(player)
    return infectedPlayers[player] 
end

You avoid the overhead of shifting values around inside table.remove :slightly_smiling_face:

2 Likes

Yeah that’s pretty much what I described.