开发者

Looping through a list to find an object with the largest number efficiently!

开发者 https://www.devze.com 2023-02-23 14:30 出处:网络
using c# i have a listthose objects all have a float mass that is randomized when the object is created.

using c# i have a list those objects all have a float mass that is randomized when the object is created.

Whats the most efficient way to loop through the list and find the object w开发者_如何学运维ith the highest mass?


The most efficient way to do this with a simple list will be a simple linear time search, as in

SomeObject winner;
float maxMass = 0.0f; // Assuming all masses are at least zero!
foreach(SomeObject o in objects) {
    if(o.mass > maxMass) {
        maxMass = o.mass;
        winner = o;
    }
}

If this is something you intend to do regularly, it may be beneficial to store your objects in an order sorted by mass and/or to use a more appropriate storage container.


Sounds like a perfect candidate for the MaxBy/MinBy operators in morelinq. You could use it as follows:

objects.MaxBy(obj=>obj.Mass)


Implementing IComparable would make things simple and easy to maintain. I have provided an example. Hope this helps. I am not sure if this is more efficient than looping. I understand that sometimes using linq slightly degrades the performance for the first time when it is invoked.

But definitely many a times maintainable code scores more over slight performance gain. Can someone provide more details on performance of PARALLEL execution vs looping with AsParallel().

class Program
{
    delegate int Del();
    static void Main(string[] args)
    {
        List<MyClass> connections = new List<MyClass>();
        connections.Add(new MyClass() { name = "a", mass = 5.001f });
        connections.Add(new MyClass() { name = "c", mass = 4.999f }); 
        connections.Add(new MyClass() { name = "b", mass = 4.2f });
        connections.Add(new MyClass() { name = "a", mass = 4.99f });

        MyClass maxConnection = connections.AsParallel().Max();
        Console.WriteLine("{0} {1} ", maxConnection.name, maxConnection.mass);
        Console.ReadLine();
    }

    class MyClass : IComparable
    {
        public string name { get; set; }
        public float mass { get; set; }

        public int CompareTo(object obj)
        {
            return (int)(mass - ((MyClass)obj).mass);
        }
    }
}


The simplest and most efficient solution (assuming repeated queries) is to sort the list by size.

i.e.

private int SortByMass(ObjectWithMass left,ObjectWithMass right)
{
  return left.Mass.CompareTo(right.Mass);
}    
List<ObjectWithMass> myList = MyFunctionToPopulateTheList();
myList.sort(SortByMass);

Once the list is sorted, the first element will be the smallest, and the last will be the largest. You can use myList.Reverse() if you want it by largest to smallest.

This runs in o(nlog(n)) to sort, and then finding the largest object is myList[myList.Count -1]. which is o(1) for .net lists (they are actually arrays underneath)


If you're willing to trade a little space for time then, in one of the instance constructors, have something like the following

public Foo(Foo min, Foo max)
{
   min = min ?? new Foo();  
   max = max ?? new Foo();

   if(max.mass < this.mass)
    max = this;

   if(min > this.mass)
    min = this;
}

And upon object creation have the calling method pass those paramters.

Foo min, max = null;

//Create a bunch of Foo objects

var Foos = from n in Enumerable.Range(0, 10000) select new Foo(min, max);
0

精彩评论

暂无评论...
验证码 换一张
取 消