Find Child With Name And Class

Even though I know that having name clashes no matter between the same class or different classes is not a good practice at all.

But I wonder: Is there any method to search for a child with a specific name and className?

For example there are:

workspace
  --InsA (Part)
  --InsB (Part)
  --InsA (ModuleScript)

how am I supposed to get InsA, the Part one? Is it even possible?

I know this will not be practical in any sense but I’m messing with studio and found this interesting.

ps: or do you have to do

local function FindInstanceWithNameAndClass (Parent,Name,Class,Recursive)
	local Descendants = if Recursive then Parent:GetDescendants() else Parent:GetChildren()
	for _,Descendant in Descendants do
		if Descendant.Name == Name and Descendant.ClassName == Class then return Descendant end
	end
	return nil
end

which don’t seem efficient. But actually, how internally FindFirstChild() etc. work like this too (though ofc it’s compiled in C and is faster)?

4 Likes

Just use FindFirstChild() and FindFirstChildOfClass() together?
For example.

local MatchNameAndClass = workspace:FindFirstChild("I Am Target") and workspace:FindFirstChildOfClass("Part")

This will return a part which’s in the Workspace and named with “I Am Target”

2 Likes

Thanks for your reply but, are you sure it’s doable?
I currently don’t have access to studio but according to what I know about Luau, and will return the first param if it’s false or nil or else returns the second param.

so your code will probably have only two possible results:

  1. nil -resulted by the instance with either name or class not found
  2. result of Parent:FindFirstChildOfClass(Class) -nil or instance will that class

so it probably can’t work and return the instance with both name and class matching. Though I can’t test in studio now, if I’m wrong then please correct me and I will have to take a look at Luau syntax in detail again lol.

Though my function earlier

did work well, and is not inefficient after some testing done earlier.

ps: also it’s recommended to use value = if statement1 then value1 else value2 instead of using and or or mentioned in Luau API (though in some cases I still prefer or)
for example:

local test = if true then (if false then 1 else 2) else 3

will be 2. (not sure if you know this already though)

Yes it works. This is an example that how I did it.
local toolFolder = player.Backpack:FindFirstChild("Tools[HandCuff]") and player.Backpack:FindFirstChildOfClass("Folder")

And the toolFolder var will be the Folder that named “Tools[HandCuff]” and, which I am looking for.
But you have to make sure that the Folder is exist, or it will be an error.

1 Like

Well I tested and it turns out that it won’t. It probably only works in your specific case.
I built a test game with the following structure (I know it’s not practical AT ALL):

image

and used the following script:

local function FindInstanceWithNameAndClass (Parent,Name,Class,Recursive)
	local Descendants = if Recursive then Parent:GetDescendants() else Parent:GetChildren()
	for _, Descendant in Descendants do
		if Descendant.Name == Name and Descendant.ClassName == Class then return Descendant end
	end
	return nil
end

local part = workspace:FindFirstChild("Part",true) and workspace:FindFirstChildOfClass("Decal")
print(part) --> nil (finds nothing, everything loaded)
part = FindInstanceWithNameAndClass(workspace,"Part","Decal",true)
print(part) --> Part (the actual one I needed)

so basically your method won’t work sadly.

I tested with recursive on, but I believe that it’s likely to error even without recursive.

1 Like

As you already said, it’s better to distinct instances by name.

I wouldn’t mind using your function. In fact, the exact logically same one can be found among my utilities, although I very rarely use it).

FindFirstChild() and related functions all perform a linear search with no guaranteed order. Your inference about internal implementation sounds right, and a custom function is just a tad slower version.

I wouldn’t strees over execution time too much, unless the search is done on a large pool of instances. Usually, it ought to be clear where approximately the instance should be, to reduce the queried collection. In concrete examples, workspace:FindFirstChild("Name", true) looks terribly wrong.


Regarding a combination of `FindFirstChild()` and `FindFirstChildOfClass()` or `FindFirstChildWhichIsA()`

Relying on this combined search is not safe! The result is not what one would expect at a quick glance. It’s based on how ternary operators work!

The decal in your test is inside an instance, and the second search (FindFirstChildOfClass) is not recursive, so the result is Part and nil, which makes it nil.

Why is this not safe?

Look at the following two demonstrations.

local instance1, instance2 = Instance.new("IntValue"), Instance.new("Part")
local i = instance1 and instance2
print(i) --> Part

Why? Because instance1 serves as a truthy condition.

image

local path = folder:FindFirstChild("Part") and folder:FindFirstChildOfClass("ModuleScript")
local module = require(path) -- all good :)

In this case, if FindFirstChild() doesn’t return anything, the path is not even an instance reference but a falsy boolean.

local path = false and folder:FindFirstChildOfClass("ModuleScript")
print(path, typeof(path)) --> false, boolean

Which is, in Luau specific ternary operators, identical to:

local path = if false then folder:FindFirstChildOfClass("ModuleScript") else false

If you really have to find an instance with a name and a class, just use a custom function like yours.

Updates.

The changes are an additional example and some rephrased sentences for clarity.

3 Likes

well my second search was set to recursive, and it doesn’t rely on ternary statements like and and or, so I’m a little confused what do you mean by

are you referring to the first search that indeed is incorrect?
Even if yes, what do you mean by

?

Also I know how and behave, it returns the first false or nil statement, or else returns the second.

Didn’t a search in your function work fine? Yes, I was refering to the FindFirstChild() and FindFirstChildOfClass() search, which does include ternary operators.

I added a demo in the first reply.

That FindFirstChildOfClass() doesn’t have a second parameter for recursive search. It can only look for direct children, and the decal is not.

1 Like

Oh I see what you mean.
I thought you were referring to the second assign but not search
Sorry for the misunderstanding, I totally see what you mean and I knew that before. Thanks for pointing it out anyways though.

Sir, what you are doing in code you provided is not what I mean. But the way I find child with name and class is not suitable when there are two object that have a same name and class name.

Ok now I see, but actually what do you want to achieve with your code? I find it quite hard to figure out what ternary operators will do with these two completely different params.
Do you assume there will be no name clashes and want to check If the only instance with that name is of that class?
If I’m wrong pls correct me.

I assume that you know what will be in the location where you are looking for. If you are sure that this will work in your case, this may make your work easier. (even idk why did I do it in the sample that I showed you lol, but this just works and fit what I need)

Yeah I see. Anyways my method is not practical, I’m just messing with studio lol.

This doesn’t work efficiently.

Lets say you’re trying to find something inside of the HumanoidRootPart with the Name Debris and Class Of Motor6D.

Your line of code should look like this:
local Debris = HumanoidRootPart:FindFirstChild("Debris") and HumanoidRootPart:FindFirstChildOfClass("Motor6D")

However, when you print the name and classname of the Debris variable, you get the following output:
print(Debris.Name, Debris.ClassName) -> RootJoint Motor6D

How is this happening?
Well to put it simple the “HumanoidRootPart:FindFirstChild(“Debris”)” part inside of the variable acts as a boolean. The rest of the code after the last “and” is ran like normal.

If you have anything to let me know to counter this claim, let me know. I’d love to learn more luau, but I’m pretty sure my 5+ years of experience knows this pretty well.

Edit: Ah shoot. I replied to the wrong reply. My bad!

1 Like

The script you posted looks fine. Maybe shorten up the name a bit if you don’t like how long the line is… for _,d in. Anyways it’s going to go through every file anyways so…

“for _, d” is an awful change. You should always aim to write concise variables—variables that give a lot of information clearly and in a few words; brief but comprehensive. For more information on this, CodeAesthetic put out a great video titled “Naming Things in Code”

Well if you have to… Don’t matter much to me. Try assembler for a week and you’ll change your mind about that quickly. This is just a for loop … easy enough to read back.

Before you reply, understand this is all personal preference. Do whatever you’re comfortable with.
I tend to use n or t for most every for loop.

This isn’t assembly. Practically every IDE out there is shipped with auto-completion. It takes less keyboard strokes than ever to write variables names, so there’s no real advantage to abbreviation. This is even true for some assembly-dedicated IDEs, so you’re really just making your life harder; there are more cons than pros when talking poor readability

Just a way to shorten up the line. Why are you commenting on this when it has nothing to do with the question…

This entire comment section is about balancing solutions. I agree with you in the fact that the original code is perfectly fine, but abbreviation isn’t the way to go about improving the function’s readability. If anything, OP should be expanding his one-liner. One-line if statements are against Roblox’s official style guide, and I fully back this