Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get a List of Max values across a list of lists

Tags:

c#

list

linq

max

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.

like image 940
Johannes Wentu Avatar asked Oct 21 '25 13:10

Johannes Wentu


2 Answers

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);
}
like image 97
MarcinJuraszek Avatar answered Oct 24 '25 02:10

MarcinJuraszek


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.

like image 28
Christos Avatar answered Oct 24 '25 03:10

Christos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!