2015-07-07 2 views
0

Предположим, что у меня есть следующий список в любом порядке:Лучший способ перечислить все комбинации

S1 
R1 
R2 
S2 
S3 

Мне нужно создать список, где каждый «S» содержит каждый «R» комбинацию

Выход:

S1 => R1 
S1 => R2 
S2 => R1 
S2 => R2 
S3 => R1 
S3 => R2 

Каков наилучший способ достичь этого? спасибо

+0

Это звучит как 2 списка, а не один. Вам нужны комбинации всех элементов в списке S с R-списком. Мышление таким образом делает работу такой же простой, как вложенный цикл. –

+0

Список пар для элементов R для перехода в другой список, O (n). Для каждого оставшегося S постройте словарь, который каждый элемент S указывает на тот же список с элементами R. –

+1

Походит на «Декартово произведение» (http://stackoverflow.com/questions/1741364/efficient-cartesian-product-algorithm) - не действительно уверен, что это то, о чем вы просите. –

ответ

5

Try:

var byPrefix = list.GroupBy(i => i.First()).ToDictionary(g => g.Key, g => g); 
var result = 
    from s in byPrefix['S'] 
    from r in byPrefix['R'] 
    select new { s, r }; 
+0

'SelectMany' на помощь – leppie

+1

' ToDictionary' позволяет индексировать доступ и избегает избыточных итераций. – Jacob

+0

Да, я понимаю, это намного сложнее, чем я думал без него :) – leppie

1

Как упоминалось в Pranav и huseyin, вам просто нужно разбить на два списка, а затем использовать вложенные foreach для их прокрутки.

var startingList = new List<string> { "S1", "R1", "R2", "S2", "S3" }; 
List<Tuple<string, string>> result = new List<Tuple<string, string>>(); 

foreach(var s in startingList.Where(x => x.StartsWith("S")).ToList()) 
{ 
    foreach(var r in startingList.Where(x => x.StartsWith("R")).ToList()) 
    { 
     result.Add(new Tuple<string, string>(s, r)); 
    } 
} 
0

Если это всегда статичны, я имею в виду всегда два списка (или preffixes), вы можете сделать вложенные циклы:

 List<string> list = new List<string>(); 
     list.Add("S1"); 
     list.Add("R1"); 
     list.Add("R2"); 
     list.Add("S2"); 
     list.Add("S3"); 

петля

 foreach (var s in list.Where(l => l.StartsWith("S"))) 
     { 
      foreach (var r in list.Where(l => l.StartsWith("R"))) 
      { 
       Console.WriteLine(string.Format("{0} => {1}", s, r)); 
      } 
     } 

или:

 list.Where(l => l.StartsWith("S")).ToList().ForEach(s => list.Where(l => l.StartsWith("R")).ToList().ForEach(r => Console.WriteLine(string.Format("{0} => {1}", s, r)))); 

Вместо Console.WriteLine вы можете добавить t он приводит к другому списку.

0

Это то, что я придумал, смесь матрицы и счетчиками:

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var input = new string[] { 
       "S1", 
       "R1", 
       "R2", 
       "S2", 
       "S3" 
      }; 
      foreach (var item in CombinationsOfSAndR(input)) 
      { 
       Console.WriteLine("{0} -> {1}", item.Key, item.Value); 
      } 
      /* OUT: 
      S1 -> R1 
      S1 -> R2 
      S2 -> R1 
      S2 -> R2 
      S3 -> R1 
      S3 -> R2 */ 
     } 
     static IEnumerable<KeyValuePair<string, string>> CombinationsOfSAndR(string[] input) 
     { 
      for (int i = 0; i < input.Length; i++) 
      { 
       if (input[i].StartsWith("S")) 
       { 
        for (int j = 0; j < input.Length; j++) 
        { 
         if (input[j].StartsWith("R")) 
         { 
          yield return new KeyValuePair<string, string>(input[i], input[j]); 
         } 
        } 
       } 
      } 
     } 
    } 
} 
Смежные вопросы