简体   繁体   中英

Sorting a C# List<> without LINQ or delegates

I have a list of objects, each of which have a position in 3D space. I need to sort this list by distance to an arbitrary point. Currently I'm doing this with:

_attachedEffectors = _attachedEffectors.OrderBy(x =>
        Mathf.Pow((x.transform.position.x - position.x), 2) + Mathf.Pow((x.transform.position.y - position.y), 2) + Mathf.Pow((x.transform.position.z - position.z), 2)
        ).ToList();

However, unfortunately I'm constrained by using Unity's compiler which is horrible with memory allocation and LINQ/delegates. Is there any way to sort a list like this without using LINQ or delegates? Optimally a search that allocates little or no memory as I need to run this thing many times a frame.

Also in future there may be other, arbitrary constraints on the search (eg if the distance from this particular object is more than some object-specific maximum distance, ignore it)

EDIT: I don't think I clearly explained my problem. I'm aware of sorting algorithms, however, all these solutions are regarding 2 independantly comparable objects. I'm asking how to sort these objects in regards to an external variable . That is, they need to be sorted by distance to a given point in space that the objects don't know about, but the sorting algorithm does. I know this could be done by the objects knowing about this point but that screams bad design to me.

Basically, I need a Sort() implementation that takes a parameter as well as the objects to be sorted, and uses that parameter in conjunction with the objects to sort the list (as seen in the LINQ implementation - position is parameter to the function this line is in).

You could use the List.Sort() . However if you want to use this method, the object's type that is stored in your list should implement the IComparable interface. Below I provide you a sample of code, on which you can based on and write your own:

public class Customer : IComparable<Customer>
{
    public int Age { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Customer(int age, string firstName, string lastName)
    {
        Age = age;
        FirstName = firstName;
        LastName = lastName;
    }

    public int CompareTo(Customer other)
    {
        return Age.CompareTo(other.Age);
    }
}

class Program
{
    static void Main(string[] args)
    {
        List<Customer> customers = new List<Customer>
        {
            new Customer(25,"a","b"),
            new Customer(21,"c","d"),
            new Customer(22,"e","f"),
            new Customer(28,"g","i"),
            new Customer(30,"j","k"),
            new Customer(23,"l","m"),
            new Customer(31,"a","b"),
        };


        customers.Sort();

        foreach (var customer in customers)
        {
            Console.WriteLine(customer.Age);
        }

        Console.ReadKey();
    }
}

Regarding the complexity of List.Sort() method, as it is stated in MSDN ,

On average, this method is an O(n log n) operation, where n is Count; in the worst case it is an O(n ^ 2) operation.

Have a look at this table on Wikipedia. It gives you an overview of many common sorting algorithms and how they perform against others. For your purposes you can look at the ones who need O(1) memory. Just pick an algorithm and happy coding!

Something like an Insertion sort or Heapsort should suffice for your needs, depending it it has to be stable or not.

I have not used unity but you might be able to use something like this

alist.sort(delegate(someObject o1, someObject o2) {
    // Compare property1
    int compare1 = o1.proprty1.CompareTo(o2.proprty1);
    if (compare1 != 0)
        return compare1;
    // Compare property2
    return o1.proprty2.CompareTo(o2.proprty2);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM