2015-11-17 3 views
0

У меня есть следующие пары значений ключа, для которых мне нужно найти все комбинации на основе ключа. На рисунке первая таблица показывает все пары ключевых значений, а вторая таблица показывает выдержку ожидаемого результата. Все возможные комбинации должны составлять таблицу.Применить перестановку для создания таблицы

This is the extract of the table i am trying to build

public ActionResult ViewSystemValues() 
{ 
    var model = new List<ViewSystemValuesVM>();//Each item in Model consists of the Key Value pair mentioned in the question   
    var tclist = new List<TcSet>(); //Each item is the link to the Property that holds the key 
    var tcid = new List<int>(); //List of distinct keys in tclist    

    //For simplicity I have eliminated the code that would populate the Lists and the model with the description as comments 

    string[] myArray = new string[tclist.Count()]; 
    var model1 = new List<String[]>(); 
    int tclistcount = tclist.Count(); 
    foreach(var x in model) 
    { 
     foreach (var item in model) 
     for(int i=0;i<tclistcount;i++) 
     {   
      if (tcid[i] == item.TcSetID) 
       myArray[i] = item.Value; 
     } 
     model1.Add(myArray); 
    } 
} 

подход

myArray соответствует одной строке в моей переставленной таблице. model содержит действительные пары значений ключа. Я проверяю, являются ли ключи из model и tcid такими же значениями могут быть добавлены в myArray с индексом, равным tcid, так что я получаю соответствующие значения для tcid.

Но я только получить последнюю возможную комбинацию

colour fruit vegatable 
yellow banana beans 
yellow banana beans 
yellow banana beans 
yellow banana beans 
yellow banana beans 
yellow banana beans 
+0

Ваше описание не слишком ясно (и вы не должны ссылаться на внешний пост, не имеет значения, принадлежит ли сайт SE), но ваш код имеет разные биты, которые скорее всего ошибочны (или не идеальны) , Например: две самые внешние петли foreach (foreach (var x in model) и foreach (элемент var в модели)) делают что-то, чего вы, разумеется, не хотите: итерация через все элементы в модели раз все элементы модели ; на самом деле вы даже не используете переменную, повторяющуюся через первый цикл (x). Другая не слишком правильная проблема (и/или странная) - var model1 = new. Список () ;. – varocarbas

+0

Кроме того, исходное сообщение (содержимое которого должно быть включено здесь) не описывает четко то, что вы хотите. Создание алгоритма для вас здесь не совсем по теме (и я думаю, что ни в программистах); но вы можете получить некоторые подсказки, если вы правильно описываете ситуацию. Например: предоставить образец ввода (упрощенный) и описать точное поведение, которое вы хотите выполнить. – varocarbas

+0

Но разве я не включил образец вывода и вывод, который я получаю сейчас? И в предыдущем вопросе есть изображение ввода. Но я могу добавить набор входных данных к этому вопросу. – Vini

ответ

1

делать ли это, что вы хотите?

Func<string[][], string[][]> build = null; 
build = s => 
    s.Length == 1 
     ? s[0].Select(x => new [] { x }).ToArray() 
     : build(s.Skip(1).ToArray()) 
      .SelectMany(xs => s[0].Select(x => new [] { x }.Concat(xs).ToArray())) 
      .ToArray(); 

Это базовый случай в этом запросе, когда s.Length == 1 в основном превращается в new [] { new [] { "onion", "potato", "tomato", "beans" } }new [] { new [] { "onion", }, new [] { "potato", }, new [] { "tomato", }, new [] { "beans", }, }. Небазовый регистр рекурсивно вызывает build, а затем добавляет к началу каждого рекурсивного массива значения первого массива. Рад, что вы спросили?

В качестве альтернативы я мог бы написать этот запрос, как это:

Func<string[][], string[][]> build = null; 
build = s => 
(
    s.Length == 1 
     ? from x in s[0] select new [] { x } 
     : from xs in build(s.Skip(1).ToArray()) 
      from x in s[0] select new [] { x }.Concat(xs).ToArray() 
).ToArray(); 

Это может помочь вам разбить его проще.

Если я начну с этими данными:

var source = new [] 
{ 
    new { Key = "colour", Value = "red", }, 
    new { Key = "colour", Value = "blue", }, 
    new { Key = "colour", Value = "violet", }, 
    new { Key = "colour", Value = "black", }, 
    new { Key = "colour", Value = "yellow", }, 
    new { Key = "fruit", Value = "apple", }, 
    new { Key = "fruit", Value = "mango", }, 
    new { Key = "fruit", Value = "banana", }, 
    new { Key = "vegetable", Value = "onion", }, 
    new { Key = "vegetable", Value = "potato", }, 
    new { Key = "vegetable", Value = "tomato", }, 
    new { Key = "vegetable", Value = "beans", }, 
}; 

string[][] data = 
    source 
     .ToLookup(x => x.Key, x => x.Value) 
     .Select(x => x.ToArray()) 
     .ToArray(); 

Я получаю этот результат:

new [] 
{ 
    new [] { "red", "apple", "onion" } 
    new [] { "blue", "apple", "onion" } 
    new [] { "violet", "apple", "onion" } 
    new [] { "black", "apple", "onion" } 
    new [] { "yellow", "apple", "onion" } 
    new [] { "red", "mango", "onion" } 
    new [] { "blue", "mango", "onion" } 
    new [] { "violet", "mango", "onion" } 
    new [] { "black", "mango", "onion" } 
    new [] { "yellow", "mango", "onion" } 
    new [] { "red", "banana", "onion" } 
    new [] { "blue", "banana", "onion" } 
    new [] { "violet", "banana", "onion" } 
    new [] { "black", "banana", "onion" } 
    new [] { "yellow", "banana", "onion" } 
    new [] { "red", "apple", "potato" } 
    new [] { "blue", "apple", "potato" } 
    new [] { "violet", "apple", "potato" } 
    new [] { "black", "apple", "potato" } 
    new [] { "yellow", "apple", "potato" } 
    new [] { "red", "mango", "potato" } 
    new [] { "blue", "mango", "potato" } 
    new [] { "violet", "mango", "potato" } 
    new [] { "black", "mango", "potato" } 
    new [] { "yellow", "mango", "potato" } 
    new [] { "red", "banana", "potato" } 
    new [] { "blue", "banana", "potato" } 
    new [] { "violet", "banana", "potato" } 
    new [] { "black", "banana", "potato" } 
    new [] { "yellow", "banana", "potato" } 
    new [] { "red", "apple", "tomato" } 
    new [] { "blue", "apple", "tomato" } 
    new [] { "violet", "apple", "tomato" } 
    new [] { "black", "apple", "tomato" } 
    new [] { "yellow", "apple", "tomato" } 
    new [] { "red", "mango", "tomato" } 
    new [] { "blue", "mango", "tomato" } 
    new [] { "violet", "mango", "tomato" } 
    new [] { "black", "mango", "tomato" } 
    new [] { "yellow", "mango", "tomato" } 
    new [] { "red", "banana", "tomato" } 
    new [] { "blue", "banana", "tomato" } 
    new [] { "violet", "banana", "tomato" } 
    new [] { "black", "banana", "tomato" } 
    new [] { "yellow", "banana", "tomato" } 
    new [] { "red", "apple", "beans" } 
    new [] { "blue", "apple", "beans" } 
    new [] { "violet", "apple", "beans" } 
    new [] { "black", "apple", "beans" } 
    new [] { "yellow", "apple", "beans" } 
    new [] { "red", "mango", "beans" } 
    new [] { "blue", "mango", "beans" } 
    new [] { "violet", "mango", "beans" } 
    new [] { "black", "mango", "beans" } 
    new [] { "yellow", "mango", "beans" } 
    new [] { "red", "banana", "beans" } 
    new [] { "blue", "banana", "beans" } 
    new [] { "violet", "banana", "beans" } 
    new [] { "black", "banana", "beans" } 
    new [] { "yellow", "banana", "beans" } 
} 

Это работает с любым количеством клавиш.

Попробуйте эти данные:

var source = new [] 
{ 
    new { Key = "colour", Value = "red", }, 
    new { Key = "fruit", Value = "apple", }, 
    new { Key = "vegetable", Value = "onion", }, 
    new { Key = "nation", Value = "france", }, 
    new { Key = "nation", Value = "australia", }, 
}; 

Я получаю этот результат:

new [] 
{ 
    new [] { "red", "apple", "onion", "france" } 
    new [] { "red", "apple", "onion", "australia" } 
} 

Если ключ является int то код работает точно так же:

var source = new[] 
{ 
    new { Key = 1, Value = "red", }, 
    new { Key = 1, Value = "apple", }, 
    new { Key = 2, Value = "onion", }, 
    new { Key = 3, Value = "france", }, 
    new { Key = 3, Value = "australia", }, 
}; 

string[][] data = 
    source 
     .ToLookup(x => x.Key, x => x.Value) 
     .Select(x => x.ToArray()) 
     .ToArray(); 

Func<string[][], string[][]> build = null; 
build = s => 
(
    s.Length == 1 
     ? from x in s[0] select new[] { x } 
     : from xs in build(s.Skip(1).ToArray()) 
      from x in s[0] 
      select new[] { x }.Concat(xs).ToArray() 
).ToArray(); 

Вот неанонимный версия build:

public string[][] Build(string[][] source) 
{ 
    return 
    (
     source.Length == 1 
      ? from x in source[0] select new[] { x } 
      : from xs in Build(source.Skip(1).ToArray()) 
       from x in source[0] 
       select new[] { x }.Concat(xs).ToArray() 
    ).ToArray(); 
} 
+0

Не могли бы вы объяснить запрос в коде? – Vini

+1

@ViniVasundharan - Выполнено, но это, вероятно, не слишком полезно. – Enigmativity

+0

На самом деле мне нужно время, чтобы понять этот запрос. Раньше я никогда не сталкивался с чем-то подобным. И, как упоминалось в моем вопросе, количество ключей или значений теперь известно до исполнения. Но спасибо за ваш ответ. Я обязательно попробую, когда я действительно получу вашу мысль. – Vini

1

Это не реальный ответ на вопрос. Но подход, который может соблюдаться при фиксированном числе переменных.Такой подход может быть расширен для переменных входов

public ActionResult tablecreate() 
    { 
     string[] key = { "colour", "fruit", "vegetable" }; 
     var kvpair = new List<Tuple<String,String>>(); 
     kvpair.Add(new Tuple<String,String>("colour","red")); 
     kvpair.Add(new Tuple<String, String>("colour", "blue")); 
     kvpair.Add(new Tuple<String, String>("colour", "yellow")); 
     kvpair.Add(new Tuple<String, String>("colour", "black")); 
     kvpair.Add(new Tuple<String, String>("fruit", "mango")); 
     kvpair.Add(new Tuple<String, String>("fruit", "apple")); 
     kvpair.Add(new Tuple<String, String>("vegetable", "potato")); 
     kvpair.Add(new Tuple<String, String>("vegetable", "tomato")); 
     kvpair.Add(new Tuple<String, String>("vegetable", "beans")); 
     var combi = new List<Tuple<String,String,String>>(); 
     int i = 0, j = 0, k = 0; 
     var colorval = new List<String>(); 
     var fruitval = new List<String>(); 
     var vegval =new List<String>(); 
     foreach (var item in kvpair) 
     { 
      if (item.Item1 == "colour") 
       colorval.Add(item.Item2); 
      else if (item.Item1 == "fruit") 
       fruitval.Add(item.Item2); 
      else if (item.Item1 == "vegetable") 
       vegval.Add(item.Item2); 
     } 
     foreach(var col in colorval) 
     { 
      foreach(var fru in fruitval) 
      { 
       foreach(var veg in vegval) 
       { 
        combi.Add(new Tuple<string, string, string>(col, fru, veg)); 
       } 
      } 
     } 

Выходной сигнал будет генерировать таблицу, указанную в вопросе

я мог бы получить значения, которые принадлежат каждому ключу с помощью следующего кода, по-прежнему делает комбинации пропали без вести

var serialize = new List<Tuple<int, List<string>>>(); 

for(int i=0;i<tcid.Count();i++) 
{ 
     var val = new List<string>(); 
     foreach(var item in model) 
     { 
      if(tcid[i]==item.TcSetID) 
       val.Add(item.Value);   
     } 
     serialize.Add(new Tuple<int,List<string>>(tcid[i],val)); 
    } 

Сейчас в serailize у нас есть все возможные значения для каждого ключа.

Чтобы это было понятнее, serailize используется только как имя переменной. сериализный список похож на colorval, fruitval и vegval в приведенном выше коде с постоянным числом переменных.

Так serailize будет содержать значения, как показано ниже:

serialize [item1 :colour, item2 : {blue,red,black,yellow}] 
serialize [item1 :fruit, item2 : {apple,mango}] 
serialize [item1 :vegetable, item2 : {tomato,potato,beans}] 

У меня есть функция, которая будет найти декартово произведение двух элементов в serialize.item2

public List<String> Cartesian (List<String> A, List<String> B) 
{ 
    int Alenght = A.Count(); 
    int Blength = B.Count(); 
    var S = new List<String>(); 
    for (int i = 0; i < Alenght;i++) 
    { 
     for(int j=0;j<Blength;j++) 
     { 
      S.Add(A[i] + "delim" + B[j]); 
     } 
    } 
    return S; 
} 

И функция вызывается следующим

var A = new List<String>(); 
foreach(var item in serialize) 
{ 
    if(j==0) 
    { 
     A = item.Item2; 
     j = 1;  
    } 
    else 
     A = Cartesian(A, item.Item2); 
    } 

Затем, чтобы сделать строку в списке A в качестве строкового массива

//distinctlist contains all the distinct strings in A 
foreach(var item in distinctlist) 
{ 
    var row = new ViewsVM(); 
    row.row = item.Split(new string[] { "delim"},StringSplitOptions.None); 
    ViewsVM.Add(row); 
} 

ViewsVM

public class ViewsVM 
{ 
    public string[] row { get; set; } 
} 

Надеется, что это поможет кому-то. Но я должен предупредить, что это не лучший подход.

Enigmativity имеет лучший подход к решению проблемы. Я опубликовал этот ответ только потому, что нашел альтернативу для этого.

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