get a List of Max values across a list of lists

我是研究僧i 提交于 2021-02-07 20:29:46

问题


I have a List<List<double>> and I need to find a List MyList where MyList[0], for instance, is the Max of all the first elements of the List. Example, just to be clear: First list contains (3,5,1), second contains (5,1,8), third contains (3,3,3), fourt contains (2,0,4). I need to find a list with (5, 5, 8). I do NOT need the list (5,8,3,4).

Of course i know how to do it with nested for cycles. I'd like to know if there's a linq way and believe me i don't know where to start from.


回答1:


Try this one:

 // Here I declare your initial list.
 List<List<double>> list = new List<List<double>>()
 {
     new List<double>(){3,5,1},
     new List<double>(){5,1,8},
     new List<double>(){3,3,3},
     new List<double>(){2,0,4},
 };

 // That would be the list, which will hold the maxs.
 List<double> result = new List<double>();


 // Find the maximum for the i-st element of all the lists in the list and add it 
 // to the result.
 for (int i = 0; i < list[0].Count-1; i++)
 {
     result.Add(list.Select(x => x[i]).Max());
 }

Note: this solution works only, when all the lists that are contained in the list have the same number of elements.




回答2:


var source = new List<List<int>> {
    new List<int> { 3, 5, 1 },
    new List<int> { 5, 1, 8 },
    new List<int> { 3, 3, 3 },
    new List<int> { 2, 0, 4 }
};

var maxes = source.SelectMany(x => x.Select((v, i) => new { v, i }))
                  .GroupBy(x => x.i, x => x.v)
                  .OrderBy(g => g.Key)
                  .Select(g => g.Max())
                  .ToList();

Returns { 5, 5, 8}, which is what you need. And will work when source lists have different number of elements too.

Bonus

If you need version for Min too, and want to prevent code duplication, you can go a little bit functional:

private static IEnumerable<TSource> GetByIndex<TSource>(IEnumerable<IEnumerable<TSource>> source, Func<IEnumerable<TSource>, TSource> selector)
{
    return source.SelectMany(x => x.Select((v, i) => new { v, i }))
                 .GroupBy(x => x.i, x => x.v)
                 .OrderBy(g => g.Key)
                 .Select(g => selector(g));
}

public static IEnumerable<TSource> GetMaxByIndex<TSource>(IEnumerable<IEnumerable<TSource>> source)
{
    return GetByIndex(source, Enumerable.Max);
}

public static IEnumerable<TSource> GetMinByIndex<TSource>(IEnumerable<IEnumerable<TSource>> source)
{
    return GetByIndex(source, Enumerable.Min);
}



回答3:


Even if this topic is answered long time ago, I'd like to put here another solution I've made up with Linq, shorter than this other solution :

List<List<int>> mylist; //initial list of list

List<List<int>> mins_list = mylist.Aggregate(
    (x, cur) => cur.Zip(x, (a, b) => (a.Value > b.Value) ? a : b).ToList()
).ToList();

This very simple code is just aggregating every sub-list into a list of minima. Note that the internal ToList is mandatory as Zip is deferred.

You can encapsulate the code in an extension method, and do the same trick as MarcinJuraszek to generate other similar computations (min, max, mean, std, ...).




回答4:


If always you know how many elements present in your lists,you can use this approach:

var result =  new[]
        {
            list.Select(a => a[0]).Max(), 
            list.Select(a => a[1]).Max(),
            list.Select(a => a[2]).Max()
        };


来源:https://stackoverflow.com/questions/22735016/get-a-list-of-max-values-across-a-list-of-lists

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!