循环遍历列表以有效地找到具有最大数字的对象

本文关键字:数字 对象 列表 遍历 有效地 循环 | 更新日期: 2023-09-27 17:49:30

使用c#,我有一个列表,这些对象都有一个浮动质量,在对象创建时随机化。

遍历列表并找到质量最大的对象的最有效方法是什么?

循环遍历列表以有效地找到具有最大数字的对象

对于简单列表,最有效的方法是简单的线性时间搜索,如

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;
    }
}

如果您打算定期这样做,那么按质量排序存储对象和/或使用更合适的存储容器可能是有益的。

听起来像是morelinq中MaxBy/MinBy操作符的完美候选。您可以这样使用它:

objects.MaxBy(obj=>obj.Mass)

实现IComparable将使事情变得简单且易于维护。我已经提供了一个例子。希望这对你有所帮助。我不确定这是否比循环更有效。我知道有时使用linq会在第一次调用时稍微降低性能。

但是很多时候,可维护的代码比轻微的性能增益更重要。有没有人能提供更多关于并行执行和使用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);
        }
    }
}

最简单和最有效的解决方案(假设重复查询)是按大小对列表进行排序。

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

一旦列表被排序,第一个元素将是最小的,最后一个元素将是最大的。如果您希望从大到小,可以使用myList.Reverse()

运行0 (nlog(n))来排序,然后找到最大的对象是myList[myList.Count -1]。这是0(1)对于。net列表(它们实际上是数组)

如果您愿意用一点空间换取时间,那么在其中一个实例构造函数中,有如下内容

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;
}

在对象创建时,让调用方法传递这些参数。

Foo min, max = null;
//Create a bunch of Foo objects
var Foos = from n in Enumerable.Range(0, 10000) select new Foo(min, max);