Questions regarding IComparer
What is the difference between:
public class SortDistance : IComparer<EnemyInfo>
{
public int Compare(EnemyInfo a, EnemyInfo b)
{
//Sort descending
if (a.distance < b.distance) {return 1;}
else if (a.distance > b.distance) {return -1;}
else {return 0;}
}
}
And:
public class SortDistance : IComparer<EnemyInfo>
{
public int Compare(EnemyInfo a, EnemyInfo b)
{
//Sort ascending
return Comparer<float>.Default.Compare(a.distance, b.distance);
}
}
Other than sorting in opposite directions they seem to do the same thing? What is the difference?
Another question, I also have an "inSight" bool in the EnemyInfo constructor. Instead of sorting all the elements by distance. Can I sort only the elements where inSight = true? Would the if statement be placed in the SortDistance class? or in the method where I invoke Sort?
Any help appreciated, Thanks a lot.
They are the same, but on the first one the 1 and -1 are reversed. Usually 1 indicates that the first argument (or the object itself) is "greater" than the other object.
What do you want to do with the enemies that are not in sight? they have to be put somewhere when you sort the collection (unless you remove them before sorting).
Answer by Bunny83 · Dec 31, 2015 at 04:06 PM
I've never seen someone using
return Comparer<float>.Default.Compare(a.distance, b.distance);
In most cases the comparison boils down to some kind of primitive type. Those usually have a CompareTo method. So you could simply do
return a.distance.CompareTo(b.distance);
if you want to sort them in reverse order, just swap a and b.
There's no real difference between your first and second implementation besides that you reversed the sorting order.
About your second question: That doesn't make much sense. When you sort a List or generally a collection of objects you don't remove or add elements. They are simply sorted. A comparer just tells the sorting algorithm if, when comparing two elements, one element should come before or after the other or if it doesn't matter.
In most cases it doesn't make sense to create a seperate IComparer class. If you just want to be able to sort the elements, your EnemyInfo class could implement the IComparable interface. That way you can define a default sorting for your class. If you need a specific sorting order, you can simply use lambda expressions:
list.Sort( (a,b)=>a.distance.CompareTo(b.distance) );
If you want to remove certain elements from a collection you can use linq. For example:
using System,Linq;
//...
var inSightSorted = list.Where(a=>a.inSight).Sort( (a,b)=>a.distance.CompareTo(b.distance) ).ToList();
In this case we create a new list out of the old one, we remove all elements where inSight is false and sort the resulting enumeration by distance all in just one line ^^.
Thanks
The reason I do not want to remove inSight false elements is so I can keep track of last known positions of AI's that left our sight. Then I can set possible secondary targets or thirdary targets in the future.
And the reason I choose IComparer is so I can sort by multiple different variables. Can you set more than 1 type using IComparable in the constructor?
You don't need a IComparer to sort on multiple variables. An IComparer object or a Comparison delegate will do the exact same thing. So if i got you right you want to pretend that objects which have inSight == false to be at a far distance so they are sorted to the end of the list? In that case you can simply use a method like this:
public static int SortByDistCheckInSight(EnemyInfo a, EnemyInfo b)
{
if (a.inSight ^ b.inSight) // either a or b is not insight
{
if (!a.inSight)
return 1;
return -1;
}
return a.distance.CompareTo(b.distance);
}
list.Sort(SortByDistCheckInSight);
With the xor check we test if one and only one of the two objects is not in sight. If both are in sight or if both are not insight we simply sort by distance. However if one of them is not in sight but the other is we always say that the object that is not insight has a higher value than the one insight.
I'm not sure if i placed the "1" and "-1" correctly, they might need to be swapped.
If the overall sorting should be reversed you can add this method:
public static int SortByDistCheckInSightReversed(EnemyInfo a, EnemyInfo b)
{
return SortByDistCheckInSight(b, a);
}
Yes, that was what I was trying to achieve. I will check it out your solution. This stuff is tricky to wrap my head around! First time using lists let alone delegates and comparisons!
Thanks,
Your answer
![](https://koobas.hobune.stream/wayback/20220612054508im_/https://answers.unity.com/themes/thub/images/avi.jpg)