2014-01-15 4 views
2

Я имею массив списковВозможные комбинации

List<string>[] possibleLines; 

Массив может быть разного размера и каждый каждый список <> может иметь различное число строк. Фор пример

  • List<string>[0] - может иметь строки "первой строки", "вторая строка"
  • List<string>[1] - "третья строка", "четвертую строку", "пятую строку"

мне нужно получить все возможные комбинации, каждая строка должна быть из другого списка (размер массива может отличаться). Например

  • "первая строка", "четвертая строка"
  • "первая строка", "пятая строка"
  • "вторая строка", "четвертая строка"

и т.д. ,

+1

Можете ли вы опубликовать какой код вы пытались или где он не удалось? – AWinkle

+1

И чтобы уточнить, вы хотите ** комбинации **, а не ** перестановки? ** –

+2

Подсказка: вложенные петли. –

ответ

5

Что вы здесь делаете, это вычисление Декартова произведения неизвестного количества коллекций. Эрик Липперт описывает, как написать решение этой проблемы в this blog post (которое я сильно предлагает вам прочитать, как он придумал это решение).

код он заканчивается, как его результат:

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
    this IEnumerable<IEnumerable<T>> sequences) 
{ 
    IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; 
    return sequences.Aggregate( 
    emptyProduct, 
    (accumulator, sequence) => 
     from accseq in accumulator 
     from item in sequence 
     select accseq.Concat(new[] {item})); 
} 
+0

Любите статью. Я прочитал его и должен был визуализировать происходящее. Добавлен ответ, который добавляет визуализирующий код в это решение. +1 за отличную статью! –

+0

Спасибо, мне кажется, что я хочу. Но я не использую его, я хочу получить эти комбинации. Не могли бы вы привести пример. – user2412672

+0

@ user2412672 Вы называете 'CartesianProduct' на' possibleLines', и он дает вам последовательность последовательностей, где каждая внутренняя последовательность представляет одну комбинацию. Вы можете «вывести» итоговый результат, чтобы что-то сделать для каждой комбинации, а затем, например, 'foreach' каждой комбинации, чтобы распечатать их. – Servy

1

Я думал, что это было довольно прохладно математика проблемы, но я хотел бы представить себе реальный процесс, так что я написал это для тех, кто хочет проверить , что Servy (ну, Эрик Липперт) писал:

int length = 4; 
var lists = new List<List<string>>(); 
var random = new Random(1234); 

for(int i = 0; i < length; i++) 
{   
    var inLength = random.Next(4, 8); 
    var tempList = new List<string(); 
    for (int j = 0; j < inLength; j++_ 
    { 
     tempList.Add(string.Format("{{String Coords: {0}, {1}}}", i, j)); 
    } 
    lists.Add(tempList); 
} 

var cp= lists.CartesianProduct(); 
var output = RenderString(cp); 

и RenderString:

private static string RenderString(IEnumerable<IEnumerable<string>> cp) 
{ 
    var sb = new StringBuilder(); 

    foreach (var item in cp) 
    { 
     sb.AppendLine(item.Aggregate((a, b) => a + b)); 
    } 
    return sb.ToString(); 
} 

Это даст вам output, который выглядит как

{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 0} 
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 1} 
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 2} 
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 3} 
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 0}{String Coords: 3, 4} 
{String Coords: 0, 0}{String Coords: 1, 0}{String Coords: 2, 1}{String Coords: 3, 0} 
... 
{String Coords: 0, 4}{String Coords: 1, 4}{String Coords: 2, 6}{String Coords: 3, 4} 

Довольно прохладно, если вы хотите, чтобы визуализировать то, что происходит.

+0

Вы не должны использовать 'Агрегат' для создания строк. Вы в конечном итоге создаете множество промежуточных строк, которые не нужны. И использование SB является более подробным, чем необходимо. Просто используйте 'string.Concat'. 'RenderString' может быть реализован как' return string.Concat (cp.Select (s => string.Concat (s) + "\ n")); 'и он будет короче, понятнее и значительно более эффективен в время и память. – Servy

+0

Спасибо за информацию! –

Смежные вопросы