2015-08-16 4 views
5

У меня есть данные в следующем формате:Перестановка Таблица данных с помощью Linq

(Table: Hours) 
{ Date = "21/04/2008", Person = Sally, Hours= 3 } 
{ Date = "21/04/2008", Person = Sam, Hours = 15 } 
{ Date = "22/04/2008", Person = Sam, Hours = 8 } 
{ Date = "22/04/2008", Person = Sally, Hours = 9 } 

Datatypes: Date = Дата, Person = String, Hours = Integer

Использование LINQ Я хотел бы, чтобы выбрать его в этот формат:

{ Date = "21/04/2008", Sam = 15, Sally = 3 } 
{ Date = "22/04/2008", Sam = 8, Sally = 9 } 

Datatypes: Date = Дата, Сэм = Integer, Sally = Integer

Является ли это р жно?

+0

Если число лиц больше двух, значит? –

+1

@ X-TECH Я предполагаю, что это будет как {Date = "...", Person1 = .., Person2 = .., Person3 = .....} –

+0

Что такое тип 'Person'? Это класс или? –

ответ

6
from d in data 
group d by d.Date into g 
select new {Date = g.Key, People = g.Select(gg=>new{Person = gg.Person, Hours = gg.Hours})} 

Это даст вам данные, а затем это просто форматирование для правильной отображения.

+0

Это, кажется, дает мне: [{«Дата»: «21/04/2008», «Люди»: [{«Человек»: «Салли», «Часы»: 3}, {«Лицо»: «Сэм» , "часы": 15}]}, { "Дата": "22/04/2008", "Люди": [{ "Персона": "Салли", "часы": 8}, { "Персона":» Sam "," Hours ": 9}]}] – Reafidy

+0

Мне действительно нужно: [{Date =" 21/04/2008 ", Sam = 15, Sally = 3}, {Date =" 22/04/2008 ", Sam = 8, Sally = 9}] – Reafidy

+0

@ Reafidy Да, так работает анонимный тип. –

2

Как я понимаю, у вас есть таблица, в которой регистрируется количество часов, в течение которых каждый сотрудник работал с определенными данными. Я предполагаю, что он может содержать несколько журналов от человека в день. Если вы не хотите использовать LINQ вы можете использовать этот

var hours = new[] { 
         new { Date = "21/04/2008", Person = "Sally", Hours= 3 }, 
         new { Date = "21/04/2008", Person = "Sam", Hours = 15 }, 
         new { Date = "22/04/2008", Person = "Sam", Hours = 8 }, 
         new { Date = "22/04/2008", Person = "Sally", Hours = 9 }, 
         new { Date = "22/04/2008", Person = "John", Hours = 5 }, 
         new { Date = "22/04/2008", Person = "John", Hours = 2 }, 
         new { Date = "22/04/2008", Person = "Tom", Hours = 9 }, 
        }; 


var result = new Dictionary<string, Dictionary<string, int>>(); 
foreach (var workLog in hours) 
{ 
    if (!result.ContainsKey(workLog.Date)) 
     result[workLog.Date] = new Dictionary<string, int>(); 

    if (!result[workLog.Date].ContainsKey(workLog.Person)) 
     result[workLog.Date][workLog.Person] = 0; 

    result[workLog.Date][workLog.Person] += workLog.Hours; 
} 

Console.WriteLine(JsonConvert.SerializeObject(result)); 

и результат

{ "21/04/2008": { "Салли": 3, "Сэм": 15 }, "22/04/2008": { "Сэм": 8, "Салли": 9, "Джон": 7, "Том ": 9}}

+0

Можно ли изменить этот формат: [{Дата: 21/04/2008, Сэм: 15, Салли: 3}, {Дата: 22/04/2008, Сэм: 8, Салли: 9, Джон: 7, Том : 9}] – Reafidy

2

Update:

Если вы хотите, чтобы он просто был строковым литералом.

string.Concat("[", 
       string.Concat(data.GroupBy(d=>d.Date) .Select(d=> 
       { 
        var str = string.Format("{{ Date = \"{0}\", ", d.Key); 
        var ds = d.Select(p=>string.Format("{0} = {1}, ", p.Person, p.Hours)).ToArray(); 
        return string.Concat(str, string.Concat(ds), " },"); 
       })), 
       "]"); 

Если вы хотите быть куча objects с такой структурой:

Вот решение:

class Program 
{ 
    public class Data 
    { 
     public string Date; 
     public string Person; 
     public int Hours; 
    } 

    public static void Main(string[] args) 
    { 
     var data = new Data[] 
     { 
      new Data { Date = "21/04/2008", Person = "Sally", Hours= 3 }, 
      new Data { Date = "21/04/2008", Person = "Sam", Hours = 15 }, 
      new Data { Date = "22/04/2008", Person = "Sam", Hours = 8 }, 
      new Data { Date = "22/04/2008", Person = "Sally", Hours = 9 }, 
     }; 

     var aName = new AssemblyName("DynamicModule"); 
     var mb = AppDomain.CurrentDomain 
      .DefineDynamicAssembly(aName, AssemblyBuilderAccess.RunAndSave) 
      .DefineDynamicModule(aName.Name, aName.Name + ".dll"); 

     var list = new List<object>(); 
     foreach (var d in data.GroupBy(d=>d.Date)) 
     { 
      var t = mb.DefineType("T" + d.Key); 
      t.DefineField("Date", typeof(string), FieldAttributes.Public); 
      foreach (var p in d) 
      { 
       t.DefineField(p.Person, typeof(int), FieldAttributes.Public); 
      } 
      var type = t.CreateType(); 

      object e = Activator.CreateInstance(type, 
          BindingFlags.CreateInstance, null, null, null); 
      t.GetDeclaredField("Date").SetValue(e, d.Key); 
      d.ToList().ForEach(dd=>t.GetDeclaredField(dd.Person).SetValue(e, dd.Hours)); 

      list.Add(e); 
     } 

     foreach (var e in list) 
     { 
      Console.Write("{ "); 
      foreach (var f in e.GetType().GetFields().OrderBy(f=>f.Name)) 
      { 
       Console.Write(string.Format(" {0} = {1} ", f.Name, f.GetValue(e))); 
      } 
      Console.Write(" }\n"); 
     } 

     Console.ReadKey(); 
    } 
} 

Печатает:

{ Date = 21/04/2008 Sally = 3 Sam = 15 } 
{ Date = 22/04/2008 Sally = 9 Sam = 8 } 
+0

Спасибо, но я сейчас очень рад. Ваш код намного превосходит мои знания и выглядит впечатляюще. Меня не интересуют типы данных, и я не понимаю, почему это важно, я просто хочу, чтобы строка выводилась следующим образом: '[{Date =" 21/04/2008 ", Sam = 15, Sally = 3}, { Date = "22/04/2008", Sam = 8, Sally = 9}] ', потому что это то, что график telerik на моей веб-странице принимает в json формате. – Reafidy

+0

@Reafidy Я просто понимаю, что все, что вам нужно, это получить строковый литерал, подобный этому. Это довольно просто. См. Мое обновление. –

+0

Хороший материал, вот результат, который я получаю после одной небольшой проблемы, он печатает \ slash '' [{Date = \ "21/04/2008 12:00:00 AM \", Sally = 3, Sam = 15, } {Date = \ "22/04/2008 12:00:00 AM \", Sally = 8, Sam = 9,}] "' – Reafidy

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