2009-06-17 8 views
0

dieses Beispiel Daten (in .NET-Klassen, wo Po, Sku, Anzahl Objekte sind) Gegeben:Was ist der einfachste Weg, um diese Daten in C# (linq?) Zu fixieren?

PO, Sku, Qty 
1,ABC,1 
1,DEF,2 
1,GHI,1 
1,QWE,1 
1,ASD,1 
1,ZXC,5 
1,ERT,1 
2,QWE,1 
2,ASD,11 
2,ZXC,1 
3,ERT,1 
3,DFG,1 
3,DFH,1 
3,CVB,4 
3,VBN,1 
3,NMY,1 

Ich brauche es in eine feste Spaltenformat zu transformieren, mit einem Maximum von 5 SKUs pro Zeile (die Wiederholung PO bei Bedarf für> 5):

PO, SkuA, QtyA, SkuB, QtyB, SkuC, QtyC, SkuD, QtyD, SkuE, QtyE 
1, ABC, 1, DEF, 2, GHI, 1, QWE, 1, ASD, 1 
1, ZXC, 5, ERT, 1, , , , , , 
2, QWE, 1, ASD, 11, ZXC, 1, , , , 
3, ERT, 1, DFG, 1, DFH, 1, CVB, 4, VBN, 1 
3, NMY, 1, , , , , , , , 

Output CSV sein kann (das ist, was ich ausgeben) oder .NET-Klassen - ganz gleich dort. Gibt es einen einfachen Weg, dies in Linq zu tun, indem man nach PO gruppiert, dann nach Zahlen von 5?

EDIT: Ich habe keine Kontrolle über das Zielformat. Und für alle Interessierten ist es VendorNet und VendorBridge, die diesen Unsinn erfordern.

Antwort

1

Zum einen ist hier die Abfrage, die die richtige Hierarchie von Objekten generieren. Ich verwende anonyme Typen, aber es ist einfach genug, sie zu ändern, um eigene Klassen zu verwenden.

var query = yourData 
    .GroupBy 
    (
     x => x.PO 
    ) 
    .SelectMany 
    (
     x => x.Select 
     (
      (y, i) => new { y.PO, y.Sku, y.Qty, Key = i/5 } 
     ) 
    ) 
    .GroupBy 
    (
     x => new { x.PO, x.Key } 
    ); 

LINQ Verwendung des CSV aus den Abfrageergebnissen zu erstellen, ist bisschen wie ein Hack, aber es bekommt den Job zu erledigen. (Der „Nutzen“ LINQ zu verwenden, ist, dass Sie die ursprüngliche Abfrage-Kette könnte und die CSV-Generation in einem einzigen, massiven Aussage, sollten Sie es wünschen.)

IEnumerable<string> csvLines = query 
    .Select 
    (
     x => x.Aggregate 
     (
      new { Count = 0, SB = new StringBuilder() }, 
      (a, y) => new 
      { 
       Count = a.Count + 1, 
       SB = ((a.SB.Length == 0) ? a.SB.Append(y.PO) : a.SB) 
        .Append(", ").Append(y.Sku).Append(", ").Append(y.Qty) 
      }, 
      a => a.SB.ToString() + string.Join(", , ", new string[6 - a.Count]) 
     ) 
    ); 

string csv = string.Join(Environment.NewLine, csvLines.ToArray()); 

Meiner Meinung nach ist die CSV-Erstellung ohne Verwendung von LINQ macht der Code viel besser lesbar:

StringBuilder sb = new StringBuilder(); 
foreach (var group in query) 
{ 
    int count = 0; 
    foreach (var item in group) 
    { 
     if (count++ == 0) 
     { 
      sb.Append(item.PO); 
     } 
     sb.Append(", ").Append(item.Sku).Append(", ").Append(item.Qty); 
    } 
    while (count++ < 5) 
    { 
     sb.Append(", , "); 
    } 
    sb.Append(Environment.NewLine); 
} 

string csv = sb.ToString(); 
+0

Alle Klammern gaben mir Rückblenden von Common Lisp. –

0

Hier gehen Sie. Ich habe die Ausgabe nicht wie gewünscht formatiert. Aber das sollte Ihnen eine Vorstellung davon geben, wie man Zeilen rotiert. Hoffe, das hilft :-)

public class MyClass 
{ 
     public int PO { get; set; } 
     public String SKU { get; set; } 
     public int Qty { get; set; } 

     public static IEnumerable<MyClass> GetList() 
     { 
      return new List<MyClass>() 
         { 
          new MyClass {PO = 1, SKU = "ABC", Qty = 1}, 
          new MyClass {PO = 1, SKU = "DEF", Qty = 2}, 
          new MyClass {PO = 1, SKU = "GHI", Qty = 1}, 
          new MyClass {PO = 1, SKU = "QWE", Qty = 1}, 
          new MyClass {PO = 1, SKU = "ASD", Qty = 1}, 
          new MyClass {PO = 1, SKU = "ZXC", Qty = 5}, 
          new MyClass {PO = 1, SKU = "ERT", Qty = 1}, 
          new MyClass {PO = 2, SKU = "QWE", Qty = 1}, 
          new MyClass {PO = 2, SKU = "ASD", Qty = 1}, 
          new MyClass {PO = 2, SKU = "ZXC", Qty = 5}, 
         }; 
     } 
} 

EDIT: ich die Abfrage auf Lukes Kommentar basiert behoben haben

var lQuery = 
      MyClass.GetList() 
       .GroupBy(pArg => pArg.PO) 
       .Select(pArg => new 
        { 
         Test = pArg.Select((pArg1, pId) => 
              new {ID = (pId/5), 
               pArg1.PO, pArg1.SKU, pArg1.Qty}) 
             .GroupBy(pArg1 => pArg1.ID) 
             .Select(pArg1 => 
               pArg1.Aggregate(pArg.Key.ToString(), 
                   (pSeed, pCur) => 
                   pSeed + pCur.SKU + ",")) 
         }); 
+0

danke! Ich habe diese Überladung vergessen, die einen Index liefert. shweet. – TheSoftwareJedi

+0

Diese Lösung funktioniert nicht korrekt mit anderen Varianten der Quelldaten. Fügen Sie beispielsweise am Anfang einen weiteren Datensatz mit PO = 1 hinzu und sehen Sie, was mit Ihren Ergebnissen passiert. – LukeH

+0

@Vasu Ihre Bearbeitung hat es vermasselt. Arbeitete vorher sehr gut, außer in beiden Fällen sollte es "(pSeed, pCur) => pSeed +", "+ pCur.SKU)" sein, um die Kommaplatzierung zu beheben. @Luke Was denkst du wird mit den Ergebnissen passieren? Funktioniert gut für mich. – TheSoftwareJedi

Verwandte Themen