2016-07-06 9 views
0

Ich mache einen Vergleich für zwei CSV-Dateien, die Spalten und entsprechende Werte für jede Spalte in jeder neuen Zeile hat. Spalten werden in der ersten Zeile der Datei angegeben. Jede Zeile danach enthält Daten für jede Spalte.Vergleichen von zwei CSV-Dateien nach Spalte und Wert und Anzeigen von Zeilennummern unterschiedlicher Werte

Ich versuche ein Programm zu erstellen, das Dateien mit unterschiedlichen Zeilennummern und Anzahl von Spalten verarbeiten kann und eines, das auch die Zeilennummer von Werten anzeigen kann, die sich unterscheiden und dann eine neue Textdatei erstellen, die die Zeilennummer anzeigt. Spaltenname und Wert von Datei 1 und Datei 2.

Der Vergleich sollte basierend auf einer Kennung anstelle von Zeile für Zeile erfolgen. Wenn in der Spaltenzeile bestimmte Spaltendaten fehlen, kann die Anzahl der Spalten angezeigt werden, deren Daten fehlten.

So zum Beispiel:
worker1.csv:

Namen, Alter, Größe, Geschlecht;
Bob; 21; 190; Männchen
John; 35; 182; Männchen
Rose;
Mary; 20; 175; weiblich

worker2.csv

Namen, Alter, Größe, Geschlecht
Bob; 21; 185; männlich
John; 30; 186; männlich
Maria;

output.csv

Unterschiede in Mary gefunden:
Datei 2, Zeilennummer 3, fehlt drei Werte
Unterschiede in Bob gefunden:
Datei 1, Zeile Nummer 1, Höhe: 190
Datei 2, Zeilennummer 1, Höhe: 185
Unterschiede gefunden in John:
Datei 1, Zeilennummer 2, Alter: 35, Höhe: 182
Datei 2, Zeilennummer 3, Alter: 30, Höhe: 186

Wie soll ich das machen? Ich habe in LINQ's Ausgenommen auf beiden Dateien Linien, aber wie bekomme ich die Zeilennummern?

+0

Ich würde CSV-Daten in DataTables lesen. Es gibt viele Informationen im Internet, um zwei Databases zu vergleichen. Siehe meinen Importcode bei folgendem Beitrag: http://stackoverflow.com/questions/30129406/reading-data-from-csv-to-screen-output – jdweng

+0

Willkommen beim Stack-Overflow :-) Was hast du bisher probiert? Zeig uns bitte deinen Code. Bitte schauen Sie [ask] – JimHawkins

+0

Danke :) Das stellte sich als komplizierter heraus, als ich anfangs dachte. Ich habe bereits eine unordentliche Lösung versucht, die jede Zeile in ein Diktat mit entsprechenden Schlüsseln und Werten umwandelte. Also hat eine Datei im Grunde eine Liste von Wörterbüchern gebildet, die ich dann mit den Diäten der anderen Zeile verglichen habe. Während es irgendwie funktioniert, ist es ziemlich kompliziert und es bricht sehr leicht, wenn vergleichbare Dateien eine unterschiedliche Anzahl von Zeilen haben oder wenn die andere Datei eine Zeile mit unterschiedlichen Werten hat. Ich habe meine bisherigen Lösungen meist verschrottet: D – Makezu

Antwort

1

Dies ist ein wenig komplizierter ist, dass es zuerst erscheint. Aber wenn Sie es Schritt für Schritt angehen, ist es machbar.

Ich gehe davon aus, dass Sie genug Speicher haben, um einen der Datensätze der Datei in ein Wörterbuch zu laden. Wenn Ihre Dateien sehr groß sind, werden die Dinge viel komplizierter.

Das erste, was Sie tun möchten, ist eine der Dateien in ein Wörterbuch zu laden, indiziert durch die ID.In meinem Beispiel nehme ich an, dass die ID der Name ist. Jeder Datensatz wird in einem FileLine Instanz aufgezeichnet werden:

class FileLine 
{ 
    public int LineNumber; 
    public string Name; 
    public int Age; 
    public int Height; 
    public string Gender; 
} 

Und Ihr Wörterbuch:

Dictionary<string, FileLine> File1Lines = new Dictionary<string, FileLine>(); 

Nun lesen Sie die Datei in das Wörterbuch:

int lineNumber = 0; 
foreach (var line in File.ReadLines("worker1.csv") 
{ 
    // split the line and assign the fields. 
    // End up with name, age, height, and gender variables. 
    ++lineNumber; 
    var theLine = new FileLine(
     LineNumber = lineNumber, 
     Name = name, 
     Age = age, 
     Height = height, 
     Gender = gender); 
    File1Lines.Add(theLine.Name, theLine); 
} 

Jetzt können Sie lesen die zweite Datei, suchen Sie den Eintrag im Wörterbuch nach und melden Sie eventuelle Unterschiede:

lineNumber = 0; 
foreach (var line in File.ReadLines("worker2.csv")) 
{ 
    // split the line and create a FileLine instance. 
    // we'll call it line2 
    // Then, look to see if that line is in the File1Lines dictionary. 
    FileLine line1; 
    if (!File1Lines.TryGetValue(line2.Name, out line1)) 
    { 
     // the line didn't exist in the first file 
    } 
    else 
    { 
     // Now compare individual fields 
     if (line2.Age != line1.Age) 
     { 
      // report that fields are different 
     } 
     // Do the same with other fields 
    } 
} 

Wenn Sie jetzt die Zeilen verfolgen möchten, die sich in der ersten Datei, aber nicht in der zweiten Datei befanden, erstellen Sie HashSet<string>. Wenn Sie einen Datensatz in der zweiten Datei finden, fügen Sie den Namen zum Hash-Satz hinzu . Wenn Sie mit der zweiten Datei fertig sind, können Sie Ihren Hash-Satz mit den Schlüsseln im Wörterbuch vergleichen. Wenn also Ihr Hash-Satz FoundRecords heißt, dann hätten Sie:

var recordsNotFound = File1Lines.Keys.Except(FoundRecords); 
foreach (var name in recordsNotFound) 
{ 
    // look up item in the dictionary to report not found 
} 
+0

Vielen Dank! Ich muss sagen, ich habe vergessen, die wahre Anzahl von Spalten in meinen Daten zu erwähnen: Es gibt tatsächlich über 50 mögliche Spalten, obwohl die Anzahl der Zeilen nicht so groß sein sollte. Konnte diese Lösung mit so vielen Säulen noch möglich sein? Oder sollte ich vergessen, die Unterschiede insgesamt zu berichten? – Makezu

+0

@Makezu: Es ist immer noch mit so vielen Spalten möglich. Sie können eine Klasse wie ich erstellen, mit einer Eigenschaft pro Spalte, oder Sie können ein Wörterbuch in die Klasse einfügen, um die Namen und Werte zu speichern. Es liegt an dir. Die Anzahl der Spalten sollte jedoch die Gültigkeit dieser Lösung nicht beeinträchtigen. –

0

von beiden foreach-Schleife können Sie den Unterschied zu finden, oder für-Schleife ist auch ok:

string[] content1 = File.ReadAllLines(@"worker1.csv"); 
string[] content2 = File.ReadAllLines(@"worker2.csv"); 
for(int i = 0; i < content1.Length; i++) 
{ 
    // check here every line, i is your line number 
} 
for(int i = 0; i < content2.Length; i++) 
{ 
    // check here every line, i is your line number 
} 
Verwandte Themen