Comparisons of items in Array[Resource] returning unexpected results

Godot Version

v4.2.1.stable.mono.official [b09f793f5]

Question

I have an array that holds instances of a custom resource. I want to write code on the resource script that can cycle through an array of resources of the same type looking for matches.

For reference, my resource is called thought and the array is called thoughts.

The first task I tried to perform was finding the index of a specific resource instance. Basically, I wanted to ask “where in the list am I?” I used :

thoughts.bsearch(self)

This code is in the script that defines thought, and is called on the instance I’m looking to match… so my expectation was that it would return the index, but it consistently returned 0.

Next I tried a hacky workaround of running a ‘for’ loop on the thoughts array looking for matches to a variable (if I got it to work I’d make a hash, but I already had a string input I could manually enter). That looks like this:

var i = -1
for thought in thoughts:
	i += 1
	if thought.orgin == self.orgin:
	thought_index = i

This consistently gave me the last item in the array… which is correct given that the code runs once when a new thought is created, and that thought is appended to the end of the array… BUT…
as a test I purposely gave multiple instances of the resource the same origin value, and it STILL always gave me the last item in the array. As I understand it, it should have returned an earlier instance of the resource since it encountered an equivalent value on a resource added to the array earlier.

For clarity I added a bunch of print statements that help verify what is going on and ran it 4 times with varying inputs for the orgin. Here’s the code:

func initialize(thoughts : Array[Thought]):
	print("created a thought:  orgin: " + orgin + "  description: " + description)
	thoughts.append(self)
	print("thoughts array size = " + str(thoughts.size()))
	var thought_index = thoughts.bsearch(self)
	print("thought index from bsearch= " + str(thought_index))
	var i = -1
	var found_description = ""
	for thought in thoughts:
		i += 1
		if thought.orgin == self.orgin:
			found_description = thought.description
			thought_index = i
	print("thought index from for loop = " + str(thought_index))
	print("self description " + description)
	print("description from match " + found_description)

This is the printed output:

created a thought: orgin: 1 description: a
thoughts array size = 1
thought index from bsearch= 0
thought index from for loop = 0
self description a
description from match a

created a thought: orgin: 2 description: b
thoughts array size = 2
thought index from bsearch= 0
thought index from for loop = 1
self description b
description from match b

created a thought: orgin: 3 description: c
thoughts array size = 3
thought index from bsearch= 0
thought index from for loop = 2
self description c
description from match c

created a thought: orgin: 2 description: d
thoughts array size = 4
thought index from bsearch= 0
thought index from for loop = 3
self description d
description from match d

It’s that last one that’s the problem: if I’ve repeated orgin = 2 it SHOULD have returned the second thought I made (the one with b as the description)

What is going on here? How do I reliably find matches in an array of resources?

ps. please excuse “orgin” instead of “origin”. I can’t spell.

You need to break once you find a match or the loop will continue running until all the elements of the array are processed. If you add the same element multiple times and don’t break once you hit your first match it will continue with the next element which will update the thought_index as the origin is the same.

var i = -1
for thought in thoughts:
	i += 1
	if thought.orgin == self.orgin:
		thought_index = i
		break
1 Like

ugggh. Of course it would be something simple like that… definitely a case of staring at one thing too long.

Why doesn’t .bsearch() work, though?

Not sure I never used it. The documentation says Note: Calling bsearch on an unsorted array results in unexpected behavior. so that may be a problem. I also don’t know how you would have a sorted array of Resources. You may need to use Array.bsearch_custom() to pass a Callable to compare them.

You could also try using Array.has() if you only want to know if a value is inside the array or Array.find() if you want to know its index.

Again with the simple answers. I feel like such a baby programmer. .find() is 100% the thing I was looking for and my eyes just went right over it in the documentation. Thank you so much.