Issue with table.remove

I have two tables. One is called ActiveAnimations, and the other is called Whitelist. I want to remove the objects from the Whitelist table, from the ActiveAnimations table. If those objects no longer exist, or are not within the ActiveAnimations table, I want it to do nothing.

I’m running into a problem, where when I use table.remove, it changes the index, preventing me from properly removing the objects. I’ve looked for resources, and they say to just use [1] as a constant index, but that doesn’t work for me as the ActiveAnimations table can include more than just what I am trying to remove.

I could’ve sworn I’ve fixed this before, but in my current state, my brain can’t fix what I believe should be a simple solution. I ask for assistance, please . . anyone.

Several hours stuck on this bug, I can feel my sanity slipping.

HELP . . PLEASE! :face_with_thermometer: :pray:

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- | STOP ALL ANIMATIONS FUNCTION | --
-----------------------------------------
function AnimationModule:StopAllAnimations(FadeTime, Whitelist)

	-- | FUNCTION VARIABLES.


	-- | Halting Active Animations not in Whitelist . .
	for i,v in pairs(AnimationModule.ActiveAnimations) do
			print(AnimationModule.ActiveAnimations)
			print(v.."is being reviewed")
		if table.find(Whitelist, v) == nil then
			print(v.."stopped")
			AnimationModule:StopAnimation(v, FadeTime)
		else
			print(v.."Is whitelisted!")
		end
		
	end

end
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 Like

Instead of removing items you don’t need you can instead keep items you do need. If that makes sense.

local newActiveAnimations = {}

for _,v in AnimationModule.ActiveAnimations do
	print(AnimationModule.ActiveAnimations)
	print(v.."is being reviewed")
	if table.find(Whitelist, v) == nil then
		print(v.."stopped")
		AnimationModule:StopAnimation(v, FadeTime)
	else
		print(v.."Is whitelisted!")

		-- is whitelisted, so add to the list to keep
		table.insert(newActiveAnimations, v)
	end
end

-- replace all active animations with only the whitelisted animations
AnimationModule.ActiveAnimations = newActiveAnimations

Also you should change v to something like animation, so that it’s easier to understand/read.

3 Likes

I’ll definitely start changing v to animation from now on. Appreciate it.

I can see this working if this was the script alone, but in my module, the StopAnimation function removes it from the table automatically. Is there a way to make it function based on removal, or do I have to inverse it all?

Making a new table like this would be much more performant, but if your :StopAnimation() does some extra logic it would be better to remove each time.

You could also create a new batch :StopAnimations() function that takes a list of animations to stop, and then removes them using this method. And then you’d have to split the special logic from :StopAnimation() to a seperate function.

Here’s an example of how that could look

-- private function that does extra logic
-- private so that it can only be used by the module itself (to prevent (accidental) misuse)
function stopAnimation(animation, fadeTime)
	-- put extra logic here
end

function module:StopAnimation(animation, fadeTime)
	stopAnimation(animation, fadeTime)

	-- remove the animation, you said that you're using table.remove()
	-- but you don't pass an index so I don't know what to put here
end

function module:StopAnimations(animations, fadeTime)
	local newActiveAnimations = {}

	for _,animation in self.ActiveAnimations do
		if table.find(animation, animations) then
			stopAnimation(animation, fadeTime)
		else
			table.insert(newActiveAnimations, animation)
		end
	end

	self.ActiveAnimations = newActiveAnimations
end

You could also replace {} in newActiveAnimations = {} with table.create() so that the table doesn’t need to constantly resize. But I’ll leave that up to you.


If you want to stay with your single :StopAnimation() function then you can also make your loop go backwards:

for i = #AnimationModule.ActiveAnimations, 1, -1 do
	local animation = AnimationModule.ActiveAnimations[i]
end

Because when going backwards removing an element won’t change the indexes of the animations you still have to iterate over. Though this only works if .ActiveAnimations is an array. I don’t know whether it is because your use of pairs() instead of ipairs().

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.