2013-08-20 2 views
2

Есть ли простой способ взять несколько списков одинакового размера и создать новый один из своих значений min/max в каждом индексе с помощью linq? Я имею в виду, как сравнить элементы на тот же индекс и выбрать, какой из них является минимальным или, как здесь:Объединение нескольких списков в один с помощью linq

List<List<int>> Some2dList = new List<List<int>> 
       { new List<int> { 1, 2, 3, 4, 5 }, 
        new List<int> { 5, 4, 3, 2, 1 } } ; 
List<int> NewList = new List<int>(5); 

for(int i=0; i< 5; i++) 
{ 
    int CurrentHighest=0; 
    for(int j=0; j<2; j++) 
    { 
     if (Some2dList[j][i] > CurrentHighest) 
      CurrentHighest = Some2dList[j][i]; 
    } 
    NewList.Add(CurrentHighest); 
} 
//Which gives me {5,4,3,4,5} 

я упростил эту петлю смотреть clearlier. Я знаю, что могу использовать Concat и GroupBy, а затем выбирать Max из каждого, но для простых типов и классов без ключевого значения я не могу понять это.

Редактировать: Я shoul've были более точными. Список в примере назначается вручную, но я спрашиваю о решении, которое было бы гибким для ЛЮБОГО количества списков. Кроме того, списки всегда одинакового размера.

+0

Есть ли у них всегда одинаковое количество записей в каждом? (i, e 'new double [x, 5]') – Sayse

+0

Да, нет необходимости проверять, есть ли значение. Все списки имеют одинаковый размер. – Tarec

ответ

3

Немного ненормально, но, похоже, работает. Он предполагает, что существует один список, хотя

Enumerable.Range(0, Some2dList.FirstOrDefault().Count) 
    .Select(columnIndex => 
     Some2dList.Max(row => row[columnIndex])) 
    .ToList(); 
+0

Спасибо, работает как шарм. – Tarec

+0

Не беспокойтесь. Как я уже сказал, предполагается, что существует минимум 1 список, иначе вы получите NRE на FirstOrDefault – Sayse

+2

+1. Это, вероятно, оптимальное решение для прямоугольного корпуса. Обратите внимание, что 'FirstOrDefault()' не намного лучше, чем 'First' в этом коде, поскольку он будет генерировать нулевую ссылку в любом случае. –

4

Это должно делать то, что вы ищете:

List<int> newList = Some2dList[0].Select((x, column) => Math.Max(x, Some2dList[1][column])).ToList(); 

Хитрость принимает перегрузку Выберите, что позволяет иметь индекс элемента, с которым вы работаете в выражении lambra: это делает возможным сравните два элемента в двух разных списках, расположенных по одному и тому же индексу. Очевидно, что если это минимальный размер, который вы ищете, используйте Math.Min вместо Math.Max.

Только одно, я считаю само собой разумеющимся, что два подсписчика имеют одинаковое количество элементов.

+0

Спасибо. Он отлично работает для 2 списков, но что, если у меня их больше? – Tarec

+1

+1 Я думаю, что это ответ для случая из 2-х элементов массива. Обратите внимание, что по умолчанию одно именование букв иногда очень сложно читать с помощью «x, y» для имен переменных - что-то вроде «index» или «column» вместо «y» было бы лучше. –

6

Нет ограничений на размер списка списков и списки могут быть любой длины.

List<List<int>> Some2dList = new List<List<int>>{ 
     new List<int> { 1, 2, 3, 4, 5 }, 
     new List<int> { 5, 4, 3, 2, 1 }, 
     new List<int> { 8, 9 } 
     }; 
var res = Some2dList.Select(list => list.Select((i, inx) => new { i, inx })) 
      .SelectMany(x => x) 
      .GroupBy(x => x.inx) 
      .Select(g => g.Max(y=>y.i)) 
      .ToList(); 
+0

+1 для анонимного использования. –

+1

+1. Необычный LINQ для непрямоугольной опции. Обратите внимание: если производительность важна, это, вероятно, не правильный подход из-за создания множества промежуточных коллекций. –

+0

@AlexeiLevenkov конечно. Если производительность имеет значение, тогда лучше написать версию, отличную от Linq. – I4V