2016-03-31 4 views
3

У меня есть List<T> и я хочу, чтобы получить все возможные подсписки, например:Получить Перечислимый всех суб списки существующего списка

[A, B, C, D, E] => [[A], [A, B], [A, B, C], [A, B, C, D], [A, B, C, D, E]] 

Есть простой способ сделать получить эту новые перечислима с помощью LINQ к объектам?

EDIT 1: Обратите внимание, что я только хочу «списки префиксов», а не все возможные перестановки (т.е. показан пример результата уже завершена).

EDIT 2: Обратите внимание, что я также хочу поддерживать порядок элементов.

EDIT 3: Есть ли способ, чтобы получить перечислимые в O (N) вместо O (N²), т.е. путем перебора источника только один раз, а не несколько раз и возвращения своего рода зрения на данные вместо нового списка каждый раз?

+0

Существует хороший блог о [перестановок Эрик Липперт] (https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source= Интернет & CD = 1 & хам = RJA & uact = 8 & веды = 0ahUKEwiS9afz1erLAhUDtRoKHS0KC7gQFgggMAA & URL = HTTP% 3A% 2F% 2Fericlippert.com% 2F2013% 2F04% 2F15% 2Fproducing-перестановки-часть-один% 2F & USG = AFQjCNELiYNC3091lbttaXec9OFgUqEAAw) –

+1

Мой вопрос не кажется, на перестановках, например, меня не интересует '[B, A]'? –

+0

@ Ювал Изжаков: пожалуйста, заново откройте мой вопрос, это не дубликат, спасибо. –

ответ

4

Метод очень наивное расширение:

public static class Extensions 
{ 
    public static IEnumerable<IEnumerable<T>> GetOrderedSubEnumerables<T>(
               this IEnumerable<T> collection) 
    { 
     var builder = new List<T>(); 
     foreach (var element in collection) 
     { 
      builder.Add(element); 
      yield return builder; 
     } 
    } 
} 

Использование:

void Main() 
{ 
    var list = new List<string> { "A", "B", "C", "D", "E" }; 
    Console.WriteLine(list.GetOrderedSubEnumerables()); 
} 

Результат:

Примечания это будет возвращать представление данных, как вы итерацию коллекции , Но в конце концов, если вам нужно потреблять каждую перестановку отдельно, вам нужно будет скопировать все List<T>, прежде чем вернуть их обратно. В этом случае, это следует сделать это:

public static class Extensions 
{ 
    public static IEnumerable<IEnumerable<T>> GetOrderedSubEnumerables<T>(
               this IEnumerable<T> collection) 
    { 
     var builder = new List<T>(); 
     foreach (var element in collection) 
     { 
      builder.Add(element); 
      var local = new List<T>(builder); 
      yield return local; 
     } 
    } 
} 
+0

Мне нравится ваше решение :) +1 –

+0

@ EʜsᴀɴSᴀᴊᴊᴀᴅ Спасибо :) –

+0

'' yield return'' приведет к созданию нового IEnumerable? –

0

Да, вы правы, ваше требование - это такое небольшое подмножество перестановок, которое больше не имеет никакого отношения к перестановкам. Так вот мое предложение:

var result = Enumerable.Range(1, list.Count). 
       Select(i => list.Take(i).ToList()). 
       ToList(); 
0

Вы можете перебрать диапазон количества элементов в списке и выберите подсписок следующим образом:

var list = new List<string> { "A", "B", "C", "D", "E"}; 

var query = 
    from i in Enumerable.Range(1, list.Count) 
    select list.Take(i); 

Имейте в виду, что если ваши данные не a List<T>Count может быть дорогостоящим. Также имейте в виду, что это повторяется над вашими данными более одного раза.