How to sort Objects in array by number in parentheses in the name ?

Using this string it was possible to sort objects by first letter:

Array.Sort(ObjList, (x,y) => String.Compare(x.name, y.name));

But if there are bunch of objects with names like
WayPoint(1), WayPoint(2)… it doesn’t work.

Sorting strings containing numbers won’t work as you expect because a string of “2” is considered to be greater than a string of “12”, since characters are compared sequentially.

If the only number pattern you wish to account for is the numbers in brackets, you can use IndexOf to check if the name has brackets, if it does then get the index of the left and right brackets, then get the substring between those indexes, and int.TryParse() that substring. If it’s a number, first compare the section of the strings before the number, then if they are equal, give the string with the higher number the earlier sort priority.

Alternatively, if you wish to perform a generic alphanumeric sort, one option would be to replace every number you find in the name string with a 0-padded number before comparing it (E.g. 1 would be replaced with 0000001). You could do this relatively quickly with a Regex, there’s a good example here.

1 Like

Thanks CrystalConfux, I did as you said and it works. This is my chunk of code that sorts objects by number in brackets, is here something to simplify (may be foreach loop instread of for - I didn’t get how to use foreach here):

void SortWayPoints() {
        float number1, number2;
        for(int i = 0; i < wayPointList.Length; i++){
            for(int j = 0; j < wayPointList.Length-1; j++) {
                NumberFromName(wayPointList[j], out number1);
                NumberFromName(wayPointList[j+1], out number2);
                if (number1 > number2)
                    SwapElements(ref wayPointList[j], ref wayPointList[j+1]);
       
            }
        }
    }

    void NumberFromName(Transform item, out float number) {
        int indexOfOpeningBracket = item.name.IndexOf("(");
        int indexOfClosingBracket = item.name.IndexOf(")");
        int lengthOfNumber = indexOfClosingBracket - (indexOfOpeningBracket+1);
        String numberPart = item.name.Substring(indexOfOpeningBracket+1,lengthOfNumber);
        number = float.Parse(numberPart);
    }
1 Like

I’m glad it works! That’s a selection sort so if your waypoint list never gets that big, it should be fine, but if you start having huge numbers of things to sort it will run quite slow. Also, in this case it looks like you already have to sort the whole thing twice, once using your previous List.Sort() comparator and once using the SortWayPoints() method.

If you want to upgrade it, rather than rewriting a more efficient sort (e.g. a quicksort) yourself, i’d suggest simply writing a comparison method for List.Sort(). (List.Sort() uses a quicksort for large numbers of items).

E.g.

ObjList.Sort(delegate(Transform x, Transform y)
{
  string namePartX, namePartY;
  float numberPartX, numberPartY;

  //This method is basically your NumberFromName method but needs to get the name part also.
  GetNameAndNumberPart(x, out namePartX, out numberPartX);
  GetNameAndNumberPart(y, out namePartY, out numberPartY);

  //First, compare the name part (part of the string before the number)
  if (namePartX == namePartY) {
    //The name parts are equal, so compare the numbers
    if (numberPartX < numberPartY) return -1; //Returning -1 tells theSort method that x is less than y.
    else if (numberPartX == numberPartY) return 0; //Returning 0 tells the Sort method that x is equal to y.
    else if (numberPartX > numberPartY) return 1; //Returning 1 tells the Sort method that x is greater.
  }
  else return String.Compare(namePartX, namePartY); //If the name part of the strings aren't equal then just compare them using the built in Compare method.
});