Entwickler-Ecke
Basistechnologien - Werte von erster Spalte jeder Zeile von CSV vergleichen
csharpfreak - Mo 21.10.13 14:47
Titel: Werte von erster Spalte jeder Zeile von CSV vergleichen
Hallo, ich komme nicht darauf, wie ich von einer CSV die Werte von der ersten Spalte vergleiche, um Positionszahlen hinzufügen zu können.
Was ich nun versucht habe, war die CSV in eine DataTable einzulesen, und die Positionen mit einer for-Schleife rausfiltern zu können.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| for (int i = 0; i< dt.Rows.Count ; i++) { if (dt.Rows[i].ItemArray[0] == dt.Rows[i++].ItemArray[0]) { iPos++; } else { iPos = 0; iPos++; } } |
Was ich mit dem Befehl machen wollte ist, wenn der Spaltenwert den gleichen Wert wie der nächste Spaltenwert, dann soll die Positionen weitergezählt werden (zb. 2 haben den Spaltenwert 1, die Positionszahlen wären dann 1 und 2).
Falls der nächste Spaltenwert nocht dem davorigen ähnelt, dann soll der Zähler auf 0 gesetzt werden, und die Position somit ab 1 neu hochzählen.
Wo ist mein Fehler und wie könnte ich es richtig machen
Moderiert von
Th69: C#-Tags hinzugefügt
Ralf Jansen - Mo 21.10.13 15:08
Du willst bestimmt nicht mit Rows[i++] vergleichen sondern eher mit Rows[i+1]. Sonst hättest du ja den Wert von i geändert und würdest innerhalb des If-Blocks auf eine andere Row zeigen als du vorher geprüft hast. Auch würde bei i++ erst i für den Index des Array verwendet und dann hochgezählt. Du vergleichst also im If im Moment die Row mit sich selbst. Es hätte also eh ++i sein müssen wenn du tatsächlich auch i verändern wolltest.
Auch sollte die Schleife bei count-1 aufhören sonst schaust du hinter das Array und es knallt.
csharpfreak - Mo 21.10.13 15:17
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| for (int i = 0; i< dt.Rows.Count ; i++) { DataRow dr = dt.Rows[i];
if (dt.Rows[i].ItemArray[0] == dt.Rows[i+1].ItemArray[0]) { iPos++; } else { iPos = 0; iPos++; } } |
mit +1 kriege ich eine Fehlermeldung, das sich an der Position 1 keine Zeile befinde
Moderiert von
Th69: Codeformatierung überarbeitet.
Ralf Jansen - Mo 21.10.13 15:25
Lies nochmal denn letzten Satz meiner Antwort ;)
Und wenn er schon bei Position 1 knallt ist da ja maximal 1 Row in deiner Datatable. Ein vergleich von 2 Rows macht natürlich auch nur Sinn wenn mindestens 2 Rows im Dataset sind.
csharpfreak - Mo 21.10.13 15:26
Gibt es auch einen anderen Weg, als das mit der Datatable, um die Werte aus der ersten Spalten einer CSV pro Zeile zu vergleichen?
Ralf Jansen - Mo 21.10.13 15:34
Ja. Aber ob das sinn macht?
Erklär mal kurz wofür du diese ~Positionsnummer ~ brauchst und was du im Anschluss damit machst.
Soll die z.B ins CSV zurückgeschrieben werden? Sind die Daten irgendwie sortiert? Du schaust ja scheinbar einfach auf Nachbarzeilen nur dann setzt du denn Zähler zurück. Macht es einen Unterschied ob 2 als gleich erachtete Zeilen im CSV direkt untereinander stehen oder nicht?
csharpfreak - Mo 21.10.13 15:43
Ich habe z.B eine CSV die so aufgebaut ist
"1";"W1757675";1;"";16.10.13 10:51:33;"ORD"
"1";"4000710050";2;"";16.10.13 10:52:07;"ORD"
"2";"944201015 ";1;"";16.10.13 10:54:27;"ORD"
"3";"2608597729";4;"";17.10.13 14:57:12;"ORD"
"4";"69428";1;"";17.10.13 15:00:14;"ORD"
Die erste Spalte soll dann wie ne Id sein nach der sortiert wird. Die Positionsnr brauch ich, damit diese Daten später in Form einer Rechnung angezeigt werden. Dh. bei Id = 1 wären für die Artikel 1 die Positonsnr 1 und 2 da.
Bei Id = 2 soll es dann wieder ab 1 zählen.
Ach und die Daten werden dabei in eine MSSQL - Datenbank gecshrieben
Th69 - Mo 21.10.13 15:46
Hallo csharpfreak :welcome:,
bitte formatiere deine Beiträge besser, d.h. benutze die C# oder Code-Tags. Für deinen ersten Beitrag habe ich das mal für dich schon übernommen.
csharpfreak - Mo 21.10.13 16:02
Hast du da jetzt eine Idee?
baumina - Mo 21.10.13 16:18
Ohne C# zu können würde ich folgende for-Schleife machen:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| LetzteID = 0
for-Schleife wenn LetzteID = AktuelleID dann PosNr = PosNr+1 sonst PosNr = 1 LetzeID = AktuelleID endewenn endefor |
Ralf Jansen - Mo 21.10.13 16:56
Benutzt du die jetztige DataTable denn auch zum schreiben der Daten in den SQL Server? Dann ist es nicht verkehrt das an der DataTable zu machen.
csharpfreak - Mo 21.10.13 17:10
Nein die datatable hab ich nur benutzt, damit ich irgendwie das erste Feld pro Zeile lesen kann, falls es eine bessere alternative gibt, wäre ich dafür dankbar ^^
Ralf Jansen - Mo 21.10.13 17:16
Die bessere Alternative wäre es an der Datenmenge zu machen die du zum schreiben in den SQL Server benutzt.
csharpfreak - Mo 21.10.13 21:42
wie meinst du das? weil was ich eigentlich nur wissen will ist, wie ich ich den ersten Wert jeder Zeile lesen kann und dann vergleichen kann.
Solange die Felder identisch sind, wird weiter hochgezählt, kommt ne andere Zahl, ist die erste Positionszahl = 1 und immer so weiter
Denn ich weiß die Parameter dafür nicht, mit der Datatable schien es vom Code irgendwie logisch zu passen
Ralf Jansen - Mo 21.10.13 22:31
Ich dachte das hättest du schon. Denn du hast ja das csv in eine DataTable bekommen, wozu dann auch irgendwie ein parsen der einzelnen Spalten gehört. Oder nicht?
Versuchen wir es mal mit Code wie ich mir das vorstelle
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| string path = "DeinPfadZurCSVDatei";
DataTable destination = new DataTable(); DataRow lastRow = null;
foreach (var line in File.ReadAllLines(path)) { string[] fields = line.Split(';'); if (fields.Length > 0) { string firstColumnValue = fields[0];
DataRow newRow = destination.NewRow(); if ((lastRow != null) && (lastRow["FirstColumn"].ToString() == firstColumnValue)) newRow["PositionsNummer"] = ((long)newRow["PositionsNummer"]) + 1; else newRow["PositionsNummer"] = 1; lastRow = newRow; } } |
csharpfreak - Di 22.10.13 09:12
Ich glaube du denkst zu kompliziert^^
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48:
| while ((inputLine = sr.ReadLine()) != null) {
string[] inputValues = inputLine.Split(';'); string id = inputValues[0];
for (int i = 0; i < inputValues.Length; i++) { inputValues[i] = inputValues[i].TrimStart(' ', '"'); inputValues[i] = inputValues[i].TrimEnd('"'); }
for (int i = 0; i < dt.Rows.Count - 1; i++) { if (dt.Rows[i][0] == dt.Rows[i+1][0]) { iPos++; } else { iPos = 0; iPos++; }
}
conn.Open();
SqlCommand cmd2 = conn.CreateCommand(); cmd2.CommandText = queryPos;
cmd2.Parameters.AddWithValue("@PosNr", iPos); cmd2.Parameters.AddWithValue("@EAN", inputValues[1]); cmd2.Parameters.AddWithValue("@Anzahl", inputValues[2]); cmd2.Parameters.AddWithValue("@Datum", UnixTimestamp); |
Die Datatable will ich gar nichz übertragen, ich übernehme nur speizifische Werte und übergebe diese dann nur.
Bisher krieg ich als Positionsnr nur die 1, auch wenn die ersten Felder den gleichen Wert hatten
baumina - Di 22.10.13 09:16
So wie ich das sehe, liest du zeilenweise ein, erwartest aber schon zu wissen was in der nächsten Zeile stehen soll. Deswegen ist es sinnvoller mit der vorherigen Zeile zu vergleichen und nicht mit der darauffolgenden.
csharpfreak - Di 22.10.13 09:22
Wie meinst du das? Wie würde das aussehen? dh. (dt.Rows[i-1]) ?
Das würde aber nicht funktionieren, weil es dann ja auch an der Position -1 prüfen würde
baumina - Di 22.10.13 09:29
LastRow merken, so wie Ralf es vorgeschlagen hat. Oder LastID merken so wie ich es vorgeschlagen hatte.
csharpfreak - Di 22.10.13 09:30
Geht das auch ohne Datatable?
baumina - Di 22.10.13 09:32
Wie schon erwähnt, ich kann deine Programmiersprache nicht, aber so wie ich das sehe, machst du das sowieso doppelt. 1. Schreibst du alles in eine DataTable und 2. liest du zeilenweise diene csv-Datei. Auf eins von beiden müsstest du meines Erachtens verzichten können.
csharpfreak - Di 22.10.13 10:34
Ich hab Ralfs Prinizip noch nicht so verstanden, wie ich eine Row merke ohne es in die datatable zu schreiben.
Wäre es eigentlich möglich, mit meiner bisherigen Schleife irgendwie noch eine Schleife zu setzen, der dann alle Datensätze durchläuft und dann meine Schleife und immer die nächsten Datensätze prüft?
baumina - Di 22.10.13 10:58
Also ich versuche mich mal deinen Quellcode zu korrigieren ... ohne Gewähr (ich kann C# nicht) :-)
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| string LetzteID = ""; while ((inputLine = sr.ReadLine()) != null) {
string[] inputValues = inputLine.Split(';'); string id = inputValues[0];
for (int i = 0; i < inputValues.Length; i++) { inputValues[i] = inputValues[i].TrimStart(' ', '"'); inputValues[i] = inputValues[i].TrimEnd('"'); }
if (LetzteID == inputValues[0]) { iPos++; } else { iPos = 1; LetzteID = inputValues[0]; }
conn.Open();
SqlCommand cmd2 = conn.CreateCommand(); cmd2.CommandText = queryPos;
cmd2.Parameters.AddWithValue("@PosNr", iPos); cmd2.Parameters.AddWithValue("@EAN", inputValues[1]); cmd2.Parameters.AddWithValue("@Anzahl", inputValues[2]); cmd2.Parameters.AddWithValue("@Datum", UnixTimestamp); |
csharpfreak - Di 22.10.13 12:28
Vielen Dank euch allen, so simpel war es^^
Damit hast dubmir echt weitergeholfen^^
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!