Sort Array from start to end, except for specific strings/resources

Godot Version

v4.2.1.stable.official [b09f793f5]

Question

Hi there! I’ve been looking into the sort_custom() function recently but I’ve been having trouble with something. I want to sort the player’s inventory automatically so that it sorts from beginning to end in a very simple manner, and leaves blank inventory spaces at the end. Like this:

["Item1", "", "Item4", "Item2", "", "Item3", "", ""] -> ["Item1", "Item4", "Item2", "Item3", "", "", "", ""] 

However, I haven’t quite been able to figure out if this is possible or not. Any help with this would be greatly appreciated!

Something like this? Basically if a is empty move it behind b

func move_empty_to_back(a, b):
	if a == "":
		return false
	return true

my_array.sort_custom(move_empty_to_back)

or using a lambda:
my_array.sort_custom(func(a, b): return false if a == "" else true)

1 Like

This will technically work but sort_custom isn’t “stable” so the items might not end up in the same order they started in.

In this case though you can filter instead of sort.

var inv_items: = inv_array.filter(func(item): return item != "")
var blanks: = []
blanks.resize(len(inv_array) - len(inv_items))
blanks.fill("")
inv_array.assign(inv_items)
inv_array.append_array(blanks)

I’m using array.assign(array) here because it updates the array in place, like a sort. rather than making a new array, which could be a problem if some other code was referencing the inventory using a different variable.

1 Like

This sort of worked as a base for what I was doing. I needed to repurpose it a bit since all the items are resources, and I originally thought I could just detect if the Name value for the item existed, but that ended up not being the case. I changed it around a bit and got it to work for resources after a little bit of debugging, thank you!

func sortInv():
	for i: Array in [itemInv, boxInv, keyInv, gearInv]:
		for o in range(0, len(i)):
			var invItems: = i.filter(func(item): return is_instance_valid(item))
			var blanks: = []
			blanks.resize(len(i) - len(invItems))
			blanks.fill(null)
			i.assign(invItems)
			i.append_array(blanks)

Here’s the modified code I made for it to work with resources.

Oh I think you don’t need that second for loop, the code you have already fixes the whole array i and doesn’t use o

1 Like

oops, forgot about that. that was from earlier and i guess i forgot to remove it, good catch

1 Like

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