2015-08-16 12 views
5

Mam dane w następującym formacie:Przegrupuj Tabela danych przy użyciu 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 } 

typy danych: Date = Data, osoba = łańcuch, godziny = Integer

użyciu LINQ chciałbym go wybrać w tym format:

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

Typy danych: Date = Data Sam = Integer, Sally = Integer

Czy to p kostny?

+0

Jeśli liczba osób jest większa niż dwa, to? –

+1

@ X-TECH Zakładam, że byłoby to jak {Date = "...", Person1 = .., Person2 = .., Person3 = .....} –

+0

Czym dokładnie jest typ "Person"? Czy to jest klasa, czy? –

Odpowiedz

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})} 

Daje to dane, a następnie wyświetla formatowanie.

+0

Wydaje mi się, że: [{"Date": "21/04/2008", "People": [{"Person": "Sally", "Hours": 3}, {"Person": "Sam" , "Godziny": 15}]}, {"Data": "22/04/2008", "Ludzie": [{"Osoba": "Sally", "Godziny": 8}, {"Osoba": " Sam "," Godziny ": 9}]}] – Reafidy

+0

Naprawdę potrzebuję: [{Date =" 21/04/2008 ", Sam = 15, Sally = 3}, {Date =" 22/04/2008 ", Sam = 8, Sally = 9}] – Reafidy

+0

@Reafidy Tak, tak działa anonimowy typ. –

2

Jak rozumiem, masz tabelę, która rejestruje liczbę godzin, jaką każdy pracownik pracował w określonych danych. Zakładam, że może zawierać wiele dzienników od osoby w ciągu dnia. Jeśli nie chcesz używać LINQ można użyć tego

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)); 

i wynik jest

{ "21/04/2008": { "Sally": 3 "Sam": 15 } "22/04/2008": { "Sam", 8: "Sally": 9, "John": 7, "Tom ": 9}}

+0

Czy to może być zmienione na ten format: [{Date: 21/04/2008, Sam: 15, Sally: 3}, {Date: 22/04/2008, Sam: 8, Sally: 9, John: 7, Tom : 9}] – Reafidy

2

Aktualizacja:

Jeśli chcesz, żeby była po prostu literalna.

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), " },"); 
       })), 
       "]"); 

Jeśli ma to być banda objects z taką strukturą:

Oto rozwiązanie:

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(); 
    } 
} 

Drukuje:

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

Dzięki, ale jestem teraz dobrze zdezorientowany. Twój kod wykracza daleko poza moją wiedzę i wygląda imponująco. Nie interesują mnie typy danych i nie widzę powodu, dla którego są one ważne, po prostu chcę mieć ciąg znaków w następujący sposób: '[{Date =" 21/04/2008 ", Sam = 15, Sally = 3}, { Date = "22/04/2008", Sam = 8, Sally = 9}] 'bo to jest to, co wykres teletekstu na mojej stronie akceptuje w formacie json. – Reafidy

+0

@Reafidy Po prostu zdaję sobie sprawę, że wszystko, co chcesz, to uzyskać literał łańcuchowy w ten sposób. To całkiem proste. Zobacz moją aktualizację. –

+0

Dobre rzeczy, to wynik, w którym jestem, ale jeden mały problem wypisuje \ 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

Powiązane problemy