Ich erhalte Daten von einer Datenquelle, die ich drehen muss, bevor ich die Informationen zur Anzeige an die Benutzeroberfläche senden kann. I am new to concept of pivoting & I am not sure how to go about it.
Das Problem besteht aus zwei Teilen:
Zu beachtende Punkte:
Ich habe bestimmte Spalten, die ich nicht pivotieren möchte. Ich nenne sie static columns.
Ich muss bestimmte Spalten drehen, um mehrstufige Header-Informationen zu bilden. Ich nenne sie dynamic columns
Einige Spalten müssen gedreht werden, die tatsächliche Werte enthalten. Ich nannte sie value columns
.
Es gibt NO limit für die Anzahl von dynamic, static and value columns
, die Sie haben können.
Es wird angenommen, dass wenn Daten kommen, wir zuerst Daten für statische Spalten und dann dynamische Spalten & amp; dann für Wertspalten.
Weitere Informationen finden Sie im angehängten Bild.
Dummy-Daten:
%Vor% Was Sie static columns
nennen, heißt normalerweise Zeilengruppen , dynamic columns
- Spaltengruppen und value columns
- Wertaggregate oder einfache Werte .
Um das Ziel zu erreichen, würde ich die folgende einfache Datenstruktur vorschlagen:
%Vor% Das Columns
Mitglied von PivotData
repräsentiert das, was Sie header nennen, während das Row
Mitglied - eine Liste von PivotDataRow
Objekten mit Data
Mitglied das enthält row group Werte und Values
- die Werte für den entsprechenden Columns
Index ( PivotDataRow.Values
hat immer den gleichen Count
wie PivotData.Columns.Count
).
Die obige Datenstruktur ist zu JSON serialisierbar / deserialisierbar (getestet mit Newtosoft.Json) und kann verwendet werden, um die Benutzeroberfläche mit dem gewünschten Format zu füllen.
Die Kerndatenstruktur, die für die Darstellung von Zeilengruppenwerten, Spaltengruppenwerten und Aggregatwerten verwendet wird, lautet wie folgt:
%Vor% Grundsätzlich repräsentiert es einen Bereich (Slice) einer string
-Liste mit Gleichheits- und Ordnungsvergleichssemantik. Ersteres ermöglicht die Verwendung der effizienten Hash-basierten LINQ-Operatoren während der Pivot-Transformation, während das spätere optionale Sortieren ermöglicht. Auch diese Datenstruktur ermöglicht eine effiziente Transformation, ohne neue Listen zuzuweisen und gleichzeitig die tatsächlichen Listen zu halten, wenn sie aus JSON deserialisiert werden.
(Der Gleichheitsvergleich wird durch die Implementierung der Methoden IEquatable<PivotValues>
interface - GetHashCode
und Equals
bereitgestellt. Dadurch können zwei PivotValues
-Klasseninstanzen auf der Grundlage der Werte im angegebenen Bereich als gleich behandelt werden die Elemente List<string>
der Eingabe List<List<string>>
. Ähnlich wird die Reihenfolge bereitgestellt, indem die Methode IComparable<PivotValues>
interface - CompareTo
) implementiert wird)
Die Transformation selbst ist ziemlich einfach:
%Vor% Zuerst werden die Spalten (Header) mit dem einfachen LINQ Distinct
Operator bestimmt. Dann werden die Zeilen durch Gruppieren der Quellenmenge durch die Zeilenspalten bestimmt. Die Werte innerhalb jeder Zeilengruppierung werden durch das äußere Verknüpfen von Columns
mit dem Gruppierungsinhalt bestimmt.
Aufgrund unserer Datenstrukturimplementierung ist die LINQ-Transformation ziemlich effizient (sowohl für den Raum als auch für die Zeit). Die Reihenfolge der Spalten und Zeilen ist optional, entfernen Sie sie einfach, wenn Sie sie nicht benötigen.
Beispieltest mit Ihren Dummy-Daten:
%Vor%Sie können die NReco PivotData -Bibliothek verwenden, um Pivot-Tabellen mit einer beliebigen Anzahl von Spalten auf folgende Weise zu erstellen (do not Vergessen Sie nicht, das Paket "NReco.PivotData" zu installieren:
%Vor%Standardmäßig sind Pivot-Tabellenzeilen / -spalten nach Kopfzeilen (A-Z) geordnet. Sie können die Reihenfolge nach Bedarf ändern .
PivotData OLAP-Bibliothek (PivotData, PivotTable-Klassen) kann in Projekten mit einzelnem Einsatz kostenlos verwendet werden. Für erweiterte Komponenten (wie PivotTableHtmlWriter) ist ein kommerzieller Lizenzschlüssel erforderlich.
Da wir die Größe des Ergebnisses vorbestimmen können, können wir es als mehrdimensionales Array definieren.
Lassen Sie uns einen funktionalen Ansatz verfolgen und das Ergebnis als Akkumulator behandeln, also schreiben wir einfach einen Reducer (für den Linq Aggregate
Methode).
Es wird auf einem Wörterbuch basieren, um die Transformation von der horizontalen auf die vertikale Linie abzubilden, und in einem anderen Statuswörterbuch, um seine Zeilen zu erstellen (natürlich benötigen die Wörterbücher einen Standardvergleich).
Dieses setzt voraus, dass Sie eine validierte header_info
haben, also - zuerst - musste ich den ersten Eintrag korrigieren eine Vervielfältigung des letzten.
Im Vergleich zu den anderen ist die folgende Lösung sehr effizient (es dauert nur 1 Millisekunde auf meinem Laptop, mehr als 4 Mal schneller als die angenommene Antwort).
%Vor%