Laden...

Zwei Listen "List<Typ>" zusammenführen?

Erstellt von corax02 vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.184 Views
C
corax02 Themenstarter:in
14 Beiträge seit 2008
vor 4 Jahren
Zwei Listen "List<Typ>" zusammenführen?

Hallo,
ich hab gerade nen ziemlichen hänger in meinen Gedanken (und dadurch unter umständen auch nicht das richtige in der Suche gefunden).

Ich habe ein Model-Klasse "Bestellung"


public class Bestellung
{
public string Bestellnummer{get;set;}
public DateTime? Bestelldatum{get;set;}
public int? StkZahl{get;set;}
public DateTime? RetoureDate{get;set;}
public string Name{get;set;}
}

dazu habe ich zwei Listen


var ListA = new List<Bestellung>();
var ListB = new List<Bestellung>();

ListA wird mit Daten aus der Datenbank befüllt (funktioniert)
ListB wird mit Daten aus mehreren CSV Dateien befüllt (funktioniert)

Mein aktuelles Problem, wo ich gedanklich gerade nicht weiter komme, ist die Zusammenführung beider Listen.
Beispiel:
in ListA:
Bestellnummer 0001
Lieferdatum 12.01.19
Stückzahl 3
Rücksendedatum
Name Mustermax

in ListB:
Bestellnummer 0001
Lieferdatum 12.01.19
Stückzahl 3
Rücksendedatum 18.01.19
Name Mustermax

zusammengeführt soll heraus kommen (z.b.: in ListC)
Bestellnummer 0001
Lieferdatum 12.01.19
Stückzahl 3
Rücksendedatum 18.01.19
Name Mustermax

Wichtig dabei ist, dass es in beide Richtungen und mit mehreren Feldern funktionieren muss. D.h. wenn in ListB der Name fehlt, soll dieser aus ListA genommen werden. Dabei darf der Datensatz nur einmal im Ergebnis auftauchen.

Mir fehlt gerade jeder Umsetzungsansatz und bräuchte mal ein paar Ideen.
Mit Concat und Union bin ich bisher nicht zu den gewünschten Ergebnis gekommen. Den original-Quelltext kann ich leider nicht posten, daher dieses einfache Beispiel (sorry)

Profis haben die Titanic gebaut, Amateure die Arche

P
64 Beiträge seit 2011
vor 4 Jahren

Nur mal so aus der Hüfte geschossen^^.


ListA.AddRange(ListB) 

pappt beide Listen zusammen.


var combined = ListA.Distinct();

sucht dann die Einzigartigen raus, wobei du noch GetHashCode und Equals in deiner Bestellungen Klasse überladen musst.

Grüße

T
2.219 Beiträge seit 2008
vor 4 Jahren

@panicJonny
Da er die Daten aus DB und CSV scheinbar abgleichen muss, würde dein Ansatz einen Teil der Daten verwerfen.

Ein sinnvoller Ansatz wäre z.B. die Daten im Dictionary zu speichern.
Wenn die Bestellnummer eindeutig ist, kannst du diese als Key im Dictionary verwenden.
Ich würde dabei die Einträge aus der DB einladen und in das Dictionary packen.
Danach musst du nur noch die Liste aus der CSV durchlaufen und per Bestellnummer schauen ob der Key schon vorhanden ist.
Wenn ja, kannst du die Daten im vorhandenen Datensatz abgleichen und ggf. anpassen.
Wenn nicht, fügst du den Eintrag in das Dictionary hinzu.

Am Ende hast du dann in Values des Dictionary alle eindeutigen und angepassten Einträge.
Diese kannst du dann in einer Liste packen mit new List<Bestellung>(dic.Values).

Dürfte dein Problem mit ein paar Zeilen lösen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.806 Beiträge seit 2008
vor 4 Jahren

Wenn es sich nur um eine Property handelt, die primär gemerged werden muss, kann man mit Linq einfach nen left join machen.
Wenn da mehr Logik rein muss, weil es viele Properties mit spezifischer Logik sind; dann kommt man um ein manuelles mergen nicht drum herum.

Ich bin auch mal über das TypeMerger Projekt gestolpert; habe es aber nur mal aus einem Legacy Projekt rausgehauen statt aktiv verwendet.

C
corax02 Themenstarter:in
14 Beiträge seit 2008
vor 4 Jahren

Wenn es sich nur um eine Property handelt, die primör gemerged werden muss, kann man mit Linq einfach nen left join machen.
Wenn da mehr Logik rein muss, weil es viele Properties mit spezifischer Logik sind; dann kommt man um ein manuelles mergen nicht drum herum.

Im ungünstigsten Fall müssen bis zu 14 Properties gemergt werden, was das ganze leider recht aufwendig macht.

@panicJonny
@T-Virus
Vielen Dank schon einmal für das "In die Richtung schubsen".

Profis haben die Titanic gebaut, Amateure die Arche

T
461 Beiträge seit 2013
vor 4 Jahren

Wichtig dabei ist, dass es in beide Richtungen und mit mehreren Feldern funktionieren muss. D.h. wenn in ListB der Name fehlt, soll dieser aus ListA genommen werden. Dabei darf der Datensatz nur einmal im Ergebnis auftauchen.

Irgendwie widerspricht sich das. Du willst beide Listen mit den Daten der anderen ergänzen, am Ende sollen aber Einträge nicht doppelt vorkommen.

Jetzt stellen sich folgende Fragen:

  1. benötigts du es tatsächlich, daß beide Listen ergänzt werden?
  2. gibt es da keine eindeutigen Schlüssel-Properties?
  3. Dein Vorhaben ist eine generische Umsetzung?
  4. Wird diese Verarbeitung ohne BusinessRules umgesetzt?

Grüße

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

C
corax02 Themenstarter:in
14 Beiträge seit 2008
vor 4 Jahren

Ich hoffe ich kann es hier ein bißchen aufdrößeln:

Die Quellen der Daten sind auf einer Seite eine MS SQL Tabelle, auf der anderen Seite mehrere CSV Dateien. Dies ist leider so vorgegeben. Der SQL Server bedient hier ein hauseigenes ERP System. Die CSV Dateien kommen von einem größeren Vertriebskanal (dies kann ich leider nicht beeinflussen).

Irgendwann vor kurzer Zeit wurde eingeführt, das neue Datensätze in der Datenbank einen Hash-Wert verpasst bekommen (ebenfalls in der Tabelle enthalten). Ich soll nun dafür sorgen, dass
a) die alten Daten in der Tabelle ebenfalls einen Hashwert bekommen
b) noch nicht importierte Daten aus den CSV Dateien in die Tabelle geschrieben werden.

Die Daten, welche in die Tabelle geschrieben werden sollen, muss ich erst in eine CSV Datei schreiben, da mit ein direkter Import in die Tabelle untersagt ist (dafür gibt es ein hauseigenes Framework).

Das Tabellenschema ist soweit klar, die CSV Dateien können aber in 4 unterschiedlichen Formaten auftauchen (der Vertriebskanal ändert des öfteren mal das Format, was wir leider nicht beeinflussen können).

Meine Idee war wie folgt:

  1. Daten der Tabelle in Liste A, Alle CSV-Daten in Liste B
  2. Daten in der Liste A mit den Daten der Liste B vergleichen
  3. unvollständige Daten (z.B.: Liste A) mit den zugehörigen Daten aus Liste B auffüllen und neuen Hashwert anhängen
  4. Doppelte Einträge aus der Liste entfernen
  5. Liste in eine CSV Datei schreiben

Wie üblich, interne Dokumentation leider == null

Kann auch durchaus sein, dass ich hier gerade einen vollkommen falschen Weg laufe, Hinweise nehm ich da gern entgegen 😃

Hinweis von Abt vor 4 Jahren

Keine Full Quotes
[Hinweis] Wie poste ich richtig?

Profis haben die Titanic gebaut, Amateure die Arche

C
2.121 Beiträge seit 2010
vor 4 Jahren

Mal als Gedankenstütze. Deine Idee (Schritte 1-5) würde ich etwas abändern.

Du brauchst einen eindeutigen Schlüssel, an dem du erkennst welche Bestellung aus Liste A der Bestellung in Liste B entspricht. Das könnte die Bestellnummer sein.

Eine der Listen packst du in ein Dictionary in dem du die Einträge anhand des Schlüssels wiederfindest. Dann durchläufst du alle Einträge der anderen Liste, suchst dir das passende Gegenstück aus dem Dictionary heraus und führst die Daten zusammen.
Die bearbeiteten Einträge werden aus dem Dictionary gelöscht, das Ergebnis kommt in eine dritte Liste. Was danach im Dictionary noch übrig ist musst du entsprechend behandeln.

Zum Zusammefnführen bau dir eine Methode die zwei Bestellungen übergeben bekommt und davon die Properties abgleicht.
Baue dir Hilfsmethoden, die beispielsweise zwei Strings übergeben bekommen und den nicht-leeren wieder zurückgeben. Dann sind das bei 14 Properties im besten Fall gerade mal 14 Aufrufzeilen.

Wenn du während der Programmierung erkennst dass ein Schritt sich mit vorgegebenen Funktionen optimieren lässt, bau es natürlich entsprechend um. Von Beginn an eine Automatik darauf loslassen dürfte schwierig werden, denn du weißt nur selbst was in welchem Fall ergänzt werden soll.