2010-02-10 4 views
5

У меня есть коллекция IEnumerable<IEnumerable<T>>, которую я хочу преобразовать в одну коллекцию измерений. Можно ли добиться этого с помощью универсального метода расширения? Сейчас я делаю это, чтобы добиться этого.Как преобразовать IEnumerable <IEnumerable <T>> в IEnumerable <T>

List<string> filteredCombinations = new List<string>(); 

//For each collection in the combinated results collection 
foreach (var combinatedValues in combinatedResults) 
{ 
    List<string> subCombinations = new List<string>(); 
    //For each value in the combination collection 
    foreach (var value in combinatedValues) 
    { 

     if (value > 0) 
     { 
      subCombinations.Add(value.ToString()); 
     } 
    } 
    if (subCombinations.Count > 0) 
    { 
     filteredCombinations.Add(String.Join(",",subCombinations.ToArray())); 
    } 
} 

Если невозможно получить общее решение, как можно оптимизировать его по-элегантному.

+1

вопроса в названии ответа здесь: HTTP: // StackOverflow. com/questions/1590723/flatten-list-in-linq –

ответ

3

Здесь вы идете:

var strings = combinedResults.Select 
    (
     c => c.Where(i => i > 0) 
     .Select(i => i.ToString()) 
    ).Where(s => s.Any()) 
    .Select(s => String.Join(",", s.ToArray()); 
+0

Но исходный код производит список строк, а не одну строку ... –

+0

D'oh. Исправление. –

+1

Весь этот вопрос был странным! В формулировке задался один вопрос, пример спросил другого. И вы ответили на третий, другой вопрос в целом и получили одобрение ... Я уже опубликовал правильный ответ и не получил голосов (не то, что я думаю, это просто забавно.) –

18

Для этого можно использовать метод расширения Enumerable.SelectMany.

Если я прочитал ваш код правильно, то код, который будет:

var filteredCombinations = combinatedResults.SelectMany(o => o) 
    .Where(value => value > 0) 
    .Select(v => v.ToString()); 

Редактировать: Как отметил, приведенный выше код не присоединяющиеся каждый элемент из подмножеств в строку, как оригинал код делает. Используя встроенные методы, вы можете сделать это с помощью:

var filteredCombinations = combinatedResults 
    .Where(resultSet => resultSet.Any(value => value > 0) 
    .Select(resultSet => String.Join(",", 
     resultSet.Where(value => value > 0) 
        .Select(v => v.ToString()).ToArray())); 
+0

избили меня ... –

+0

Что делать, если вы хотите, чтобы все подмножества были одним из элементов новой коллекции? Это то, что я делаю с String.Join ... –

+0

Это неверно - оно игнорирует требование 'Join'. –

3

Я лично использую Enumerable.SelectMany как suggested by driis.

Однако, если вы хотите, чтобы осуществить это самостоятельно, было бы гораздо чище делать:

IEnumerable<T> MakeSingleEnumerable<T>(IEnumerable<IEnumerable<T>> combinatedResults) 
{ 
    foreach (var combinatedValues in combinatedResults) { 
     foreach (var value in combinatedValues) 
       yield return value; 
    } 
} 
+0

да * SelectMany * лучше, но кажется, что многие люди не знают о «доходности возврата» - о чем свидетельствует этот вопрос. –

2

Вы задали два разных вопроса. Название, которое вы описали в названии, уже ответили drilis.

Но ваш пример кода - это другая проблема. Мы можем реорганизовать его поэтапно. Шаг 1, построить список subCombinations используя некоторую Linq:

List<string> filteredCombinations = new List<string>(); 

//For each collection in the combinated results collection 
foreach (var combinatedValues in combinatedResults) 
{ 
    var subCombinations = combinatedValues.Where(v => v > 0) 
              .Select(v => v.ToString()) 
              .ToList(); 

    if (subCombinations.Count > 0) 
     filteredCombinations.Add(string.Join(",",subCombinations.ToArray())); 
} 

Теперь внешний контур, оставляя нам только это:

var filteredCombinations = combinatedResults 
    .Select(values => values.Where(v => v > 0) 
          .Select(v => v.ToString()) 
          .ToArray()) 
    .Where(a => a.Count > 0) 
    .Select(a => string.Join(",", a)); 
Смежные вопросы