从对象列表中获取具有最大值的对象的最有效方法

The most efficient way to get object with max value from list of objects

我有一个名为条目的对象。它在 float 中有 min 和 max,在 string 中有 fileName。这些对象存储在列表中

List<Entry> minMaxList = new List<Entry>();

我需要找到具有最高值和最小值的对象及其文件名。

所以如果我有这样的数组

       Entry1                    Entry2                  Entry3
min  max    filename        min  max    filename      min  max    filename
| 2 | 120 |  file1.txt |  | 2 | 150 |  file1.txt |  | 5 | 150 |  file1.txt |     

我想得到值最小的对象是Entry1和Entry2,值最大的对象是Entry2和Entry3

我试过这个:

var max =  minMaxList.Max(r => r.getMax())

效果不错,但它 returns 我只有一个值,没有关于它来自何处的任何其他信息。我需要整个对象,或者至少需要这个值所在的文件名。我想知道它是否可以在一个命令中完成,或者我是否必须再次迭代列表并根据之前选择的最小值和最大值找到所有条目。

大功告成,您只需添加一个过滤器来查找匹配项:

var max =  minMaxList.Max(r => r.getMax())

var itemsWithMax = minMaxList.Where(r => r.getMax() == max);

Min.

类似

I wonder if it can be done in a single command

可能,使用复杂的分组或连接,但我会先得到有效的东西,然后尝试使其更好(记住单个查询并不总是 "better" 比多个查询)。

您始终可以过滤可枚举对象,而不是只让最大值通过:

var maxvalue = minMaxList.Max(w => w.getMax());
var maxitems = minmaxlist.Where(w => w.getMax() == maxvalue);

尝试按以下方式分组:

    var grpWithMaxVaues = minMaxList.GroupBy(c => c.getMax())
                                    .OrderByDescending(c => c.Key)
                                    .FirstOrDefault() 

        var max =   grpWithMaxVaues.FirstOrDefault();

Console.WriteLine(max.FileName);

给你,像这样。

允许您在列表的一次枚举中找到最小值和最大值,这可能比多次枚举列表更快,就像在其他答案中一样。

这里是working demonstration.

我对使用单个元素数组存储值并不完全满意,但它们使种子的值类型属性可变。这避免了不断重新分配聚合的需要。

var minMaxInfo = minMaxList.Skip(1)
    .Aggregate(
        new
        { 
            Max = new int[] { minMaxList[0].Max },
            MaxIndexes = new List<int> { 0 },
            Min = new int[] { minMaxList[0].Min },
            MinIndexes = new List<int> { 0 },
            Index = new int[] { 0 }
        },
        (r, t) =>
        {
            r.Index[0]++;       
            if (t.Min < r.Min[0])
            {
                r.Min[0] = t.Min;
                r.MinIndexes.Clear();
                r.MinIndexes.Add(r.Index[0]);
            } 
            else if (t.Min == r.Min[0])
            {
                r.MinIndexes.Add(r.Index[0]);   
            }

            if (t.Max > r.Max[0])
            {
                r.Max[0] = t.Max;
                r.MaxIndexes.Clear();
                r.MaxIndexes.Add(r.Index[0]);
            }
            else if (t.Max == r.Max[0])
            {
               r.MaxIndexes.Add(r.Index[0]);
            }

            return r;
        });

允许,

Console.WriteLine("MaxValue: {0}", minMaxInfo.Max[0]);
Console.WriteLine(
    "MaxFiles: {0}",
    string.Join(
        ", ",
        minMaxInfo.MaxIndexes.Select(i => minMaxList[i].FileName)));
Console.WriteLine("MinValue: {0}", minMaxInfo.Min[0]);
Console.WriteLine(
    "MinFiles: {0}",
    string.Join(
        ", ",
        minMaxInfo.MinIndexes.Select(i => minMaxList[i].FileName)));

你问的是解决这个问题的最有效方法。

确定最大/最小值并在之后搜索这些项目需要迭代列表两次。我会在一个循环中手动解决它

List<Entry> ResultList = new List<Entry>();
ResultList.Add(minMaxList[0]);
foreach (Entry item in minMaxList)
{
    if (item.getMax() >= ResultList[0].getMax())
    {
        if (item.getMax() != ResultList[0].getMax())
        {
            ResultList.Clear();
        }
        ResultList.Add(item);
    }
}

我发现这是最短的路。

var newList = new List<Hero>();
var maxValue = newList.OrderByDescending(x => x.Level).ToList()[0];