How to sort TArray in c++?

If i have an array of pointers:

TArray<OfClassPointers*> TheArray;

I cant do like this :

TheArray.Sort([](const OfClassPointers& ip1, const OfClassPointers& ip2) {
    			return  ip1.level <  ip2.level; // or ip1-> or even *ip->
    		});

Documentation says

use Algo::Sort(MyArray, Predicate)
but i have no idea how.

Can anyone help?

2 Likes

The array stores pointers, so the arguments of your lambda function needs to be pointers, not references.

Have you tried it? Compiler gives compilation error.

Algo::Sort(TheArray, [](const OfClassPointers* LHS, const OfClassPointers* RHS) { /* … */ });

Hi,

When you’re sorting by some property of your pointed-to type, it is simpler doing something like this:

Algo::SortBy(TheArray, &OfClassPointers::level);

… or this, if you want to sort in reverse:

Algo::SortBy(TheArray, &OfClassPointers::level, TGreater<>());

Saying that, your original code should have worked, so I’m not sure what problem you were having.

Steve

2 Likes

It is much easier to just call .Sort() on the variable holding the TArray. If you are using a custom data structure, be sure to overload the less than operator. Example of the syntax attached.

4 Likes

The way I did it was I created a static “predicate” function which returns a bool: whether the item should be sorted or not.

If you wanted to have a function that sorts items of the type AMyClass, you’d declare a public static function with a bool return type, like the following example (Since it’s static, the class you declare this function is up to you. For the sake of this example, I’ll be declaring it inside an imaginary AMyClass class):

inline static bool SortPredicate(AMyClass* itemA, AMyClass* itemB);

Then, go to the respective *.cpp file and define the predicate function. This way of handling a sort is especially useful if you want to sort based on a particular variable from the class you’re passing in. For instance, lets say we had a class representing our character that holds multiple stats like speed, strength, etc… we could make a predicate function to sort an array by the speed stat, so that higher speed stats appear at the front of the array. The function should return true if the sort should occur (I believe, at least – someone please correct me if I’m wrong).

inline bool AMyClass::SortPredicate(AMyClassitemA, AMyClassitemB)
{
    return (itemA->myVar > itemB->myVar);
}

If it seems to be sorting incorrectly, just flip the sign.
Finally, you can pass the function when using the .Sort() method on the TArray.

myArray.Sort(AMyClass::SortPredicate);

Hope that helps! :slight_smile:

3 Likes

Your example in your question compiles fine for me in MSVC 2019.

For example

TArray<USceneComponent*> TheArray;

TheArray.Sort([](const USceneComponent& ip1, const USceneComponent& ip2) {
	// access some random field just to test compile
	return  ip1.IsDeferringMovementUpdates() < ip2.IsDeferringMovementUpdates();
});

What error did you get? Did you include the file for OfClassPointers so that it’s defined wherever you are trying to sort by it?

8 Likes

Storage.Sort([&](const FItem& item1, const FItem& item2) {return item1.p> item2.p; });

Work properly

4 Likes

I had a problem with that as well, when trying to sort a TSet<AMyClass*> like this:

MySet.Sort([](const AMyClass& A, const AMyClass& B) {
return A.calculateSomeScore() > B.calculateSomeScore();
});

it would not compile, unless i declared the function “calculateSomeScore()” like this:

int32 calculateSomeScore() const; in the .h file and

int32 AMyClass::calculateSomeScore() const
{ … }

in the .cpp file.

I hope this helps anyone with the same problem, and this answer was not given here.

I struggled a bit with this 2 and it only became clear after learning what predicates are.
I also wrote some tutorials/guides on how to work with the data structures for future reference…

There is a section like below you’ll be interested in

" In this example we are passing them in by reference because the TArray::Sort() function REQUIRES your predicate to take in references even if your TArray is made up of pointers.

So TArray<UApples*> will still require a predicate using UApples&…"

1 Like