Hello there. Your issue is a relatively common one. There are two solutions that I will present to you. A simple solution is to loop through the existing table, find the element and retrieve its index, and finally remove it from the table with table.remove. There are two problems with this method. One: looping through the table is an O(n) operation, which means that you will, in the worst case, loop through the entire table (now with a list of players, the table might not get that long. However, it is useful to note for future reference). Not only that, but as the page I linked to above states (in reference to table.insert/table.remove when you specify the index it is to remove or add at), "The last two operations are not particularly efficient, as they must move elements up and down." I will demonstrate a simple implementation here:
local function removePlayer(playerName, playerList)
for index, playerToCheck in pairs(playerList) do
if playerName == playerToCheck then
table.remove(playerList, index)
end
end
end
A more efficient method would be to have a table with string indices (the player's name) and access that index directly when you wish to remove from the table. An example implementation:
folder = script.plrs;
plrTable = {};
function remove(plrName)
if plrName then
folder[plrName]:Destroy();
plrTable[plrName] = nil
end
end
function add(plrName)
local players = game.Players:GetChildren();
for p = 1, #players do
if not folder:FindFirstChild(plrName) then
local plr = Instance.new("IntValue");
plr.Name = plrName;
plr.Parent = folder;
plrTable[plrName] = true
end
end
end
while true do
wait(1)
local str = ""
for playerName, _ in pairs(plrTable) do
str..playerName..", "
end
print(str)
end
Some of the reasons I don't encourage using while wait() do can be found here. If you wish, you can read all the way down the thread for further argumentation.
Finally, I would like to address a few logic issues in your code. For some reason, you create a separate function for the player adding and removing events, but you don't use them as the argument for the :Connect() method. I realize that you can't get the player name directly from the player added/removing events, but just access that property of the player in your function. Here is an example of what I mean:
local players = game:GetService("Players")
folder = script.plrs;
plrTable = {};
function remove(player)
local plrName = player.Name
if plrName then
folder[plrName]:Destroy();
plrTable[plrName] = nil
end
end
function add(player)
local plrName = player.Name
local playerList = players:GetPlayers()
if not folder:FindFirstChild(plrName) then
local plr = Instance.new("IntValue");
plr.Name = plrName;
plr.Parent = folder;
plrTable[plrName] = true
end
end
players.PlayerAdded:Connect(add)
players.PlayerRemoving:Connect(remove)
while true do
wait(1)
local str = ""
for playerName, _ in pairs(plrTable) do
str..playerName..", "
end
print(str)
end
I also recommend defining your functions locally, but that is up to you. Example:
local function multiply(a, b)
return a*b
end
####I hope this helps. Have a great day scripting!
7 comments
use table.remove(), table.remove(Table, index)
Yeah, but that won’t remove a specific playername, I would have to know the exact index of the name.
I know that you said the other answer "seemed" more efficient, but a hash table is actually much more efficient than table.remove in a for loop.
When I set the value at x index to nil, it removes it from the table. You don't need to worry about it ovefilling.
hash tables do not have a length lol
Oh, that was unclear to me. Apologies!
No problem! In this scenario, there's not going to be much of a difference with respect to efficiency of the two methods presented. However, the longer the table, the more the search function has to work, and the more inefficient table.remove becomes.