2016-08-09 29 views
0

Ich muss:aus einer CSV-Lesen einer CSV-Datei viele Zeilen und Spalten enthält, von denen 2 ähnliche Datei

 
Horizontal-1 Acc. Filename  Horizontal-2 Acc. Filename 
RSN88_SFERN_FSD172.AT2   RSN88_SFERN_FSD262.AT2 
RSN164_IMPVALL.H_H-CPE147.AT2 RSN164_IMPVALL.H_H-CPE237.AT2 
RSN755_LOMAP_CYC195.AT2   RSN755_LOMAP_CYC285.AT2 
RSN1083_NORTHR_GLE170.AT2  RSN1083_NORTHR_GLE260.AT2 
RSN1614_DUZCE_1061-N.AT2  RSN1614_DUZCE_1061-E.AT2 
RSN1633_MANJIL_ABBAR--L.AT2  RSN1633_MANJIL_ABBAR--T.AT2 
RSN3750_CAPEMEND_LFS270.AT2  RSN3750_CAPEMEND_LFS360.AT2 
RSN3757_LANDERS_NPF090.AT2  RSN3757_LANDERS_NPF180.AT2 
RSN3759_LANDERS_WWT180.AT2  RSN3759_LANDERS_WWT270.AT2 
RSN4013_SANSIMEO_36258021.AT2 RSN4013_SANSIMEO_36258111.AT2 
RSN4841_CHUETSU_65004NS.AT2  RSN4841_CHUETSU_65004EW.AT2 
RSN4843_CHUETSU_65006NS.AT2  RSN4843_CHUETSU_65006EW.AT2 
RSN4844_CHUETSU_65007NS.AT2  RSN4844_CHUETSU_65007EW.AT2 
RSN4848_CHUETSU_65011NS.AT2  RSN4848_CHUETSU_65011EW.AT2 

In der CSV-Datei, die ich für die Header „Horizontal-1 Acc aussehen wollen Dateiname und. Horizontal-2 Acc. Dateiname "und dann zeilenweise die Namen der einzelnen Zeilen unter diesen Headern einzeln abrufen?

Irgendwelche Vorschläge?

Dank RG.

+0

Möchten Sie dies in TCL schreiben - haben Sie es deshalb mit TCL getaggt? Was hast du bisher versucht? Sobald Sie diese Zeilen haben, was wollen Sie mit ihnen machen? anzeigen sie? einen Kalk machen? –

+0

Hallo Nick Ja, es wird in tcl sein. – Reza

Antwort

1
package require csv 
package require struct::matrix 

::struct::matrix m 
m add columns 2 

set chan [open data.csv] 
::csv::read2matrix $chan m 
close $chan 

lassign [m get row 0] header1 header2 

for {set r 1} {$r < [m rows]} {incr r} { 
    puts -nonewline [format {%s = %-30s } $header1 [m get cell 0 $r]] 
    puts [format {%s = %s} $header2 [m get cell 1 $r]] 
} 

m destroy 

Ich finde, dass der einfachste Weg, mit csv Datensatz zu behandeln ist durch ein matrix verwenden. A matrix ist eine Art zweidimensionaler Vektor mit Einbauten zum Suchen, Sortieren und Neuanordnen von Spalten und Zeilen.

Erstellen Sie zuerst eine Matrix und nennen Sie sie m. Es wird zwei Spalten von Anfang an haben, aber noch keine Zeilen.

::struct::matrix m 
m add columns 2 

Öffnen Sie einen Kanal, um die Datendatei zu lesen. Übergeben Sie den Kanal und den Matrixnamen an den Befehl ::csv::read2matrix. Dieser Befehl liest die CSV-Daten und erstellt eine Matrixzeile für jede Datenzeile. Die Datenfelder sind in den Spalten gespeichert.

set chan [open data.csv] 
::csv::read2matrix $chan m 
close $chan 

die Header-Strings erhalten, abrufen Zeile 0.

lassign [m get row 0] header1 header2 

über die Datenzeilen zu durchlaufen, von 1 gehen (wenn wir nicht Header haben, 0) auf knapp m rows, Das ist die Anzahl der Zeilen in der Matrix.

Es gibt eine handliche report Einrichtung, die gut mit Matrizen funktioniert, aber ich werde nur eine for Schleife hier verwenden. Ich schätze, wie Sie die Daten darstellen möchten:

for {set r 1} {$r < [m rows]} {incr r} { 
    puts -nonewline [format {%s = %-30s } $header1 [m get cell 0 $r]] 
    puts [format {%s = %s} $header2 [m get cell 1 $r]] 
} 

Wenn Sie mit der Matrix fertig sind, können Sie es auch zerstören.

m destroy 

Lösung für das spezifische Problem in den Kommentaren.

package require csv 
package require struct::matrix 

::struct::matrix m 

set chan [open foo.csv] 
::csv::read2matrix $chan m , auto 
close $chan 

set f1 [m search column 0 "Result ID"] 
set headerRow [lindex $f1 0 1] 
set f2 [m search rect 0 $headerRow 0 [expr {[m rows] - 1}] ""] 
set f3 [m search row $headerRow "Horizontal-1 Acc. Filename"] 
set f4 [m search row $headerRow "Horizontal-2 Acc. Filename"] 

set top [expr {$headerRow + 1}] 
set bottom [expr {[lindex $f2 0 1] - 1}] 
set left [lindex $f3 0 0] 
set right [lindex $f4 0 0] 

puts [format {Vector=[ %s ]} [concat {*}[m get rect $left $top $right $bottom]]] 
m destroy 

Offensichtlich müssen Sie den Dateinamen auf den richtigen Namen ändern. Es gibt keine Fehlerbehandlung: In einem so einfachen Skript ist es besser, nur das Skript fehlschlagen zu lassen und alles zu korrigieren, was schief gelaufen ist.


Lösung für das zweite Problem, Kommentare unter:

package require csv 
package require struct::matrix 

::struct::matrix m 

set chan [open _SearchResults.csv] 
::csv::read2matrix $chan m , auto 
close $chan 

set f1 [m search column 0 {Result ID}] 
set headerRow [lindex $f1 0 1] 

set f2 [m search -glob rect 0 $headerRow 0 [expr {[m rows] - 1}] { These*}] 
set numofRow [lindex $f2 0 1] 

set headercol1 [m search row $headerRow { Horizontal-1 Acc. Filename}] 
set headercol2 [m search row $headerRow { Horizontal-2 Acc. Filename}] 

set indexheaderH1col [lindex $headercol1 0 0] 
set indexheaderH2col [lindex $headercol2 0 0] 

set rows [m get rect $indexheaderH1col [expr {$headerRow+1}] $indexheaderH2col [expr {$numofRow-1}]] 

set rows [lmap row $rows { 
    lassign $row a b 
    list [string trim $a] [string trim $b] 
}] 

foreach row $rows { 
    puts [format {%-30s %s} {*}$row] 
} 

puts [format {Vector=[ %s ]} [concat {*}$rows]] 

Kommentare:

  • Sie brauchen nicht die Anzahl der Spalten zu setzen, wenn Sie read2matrix mit auto
  • verwenden
  • In dieser Datei befindet sich nach der Tabelle keine leere Zelle.Stattdessen müssen wir nach einer Zeichenfolge suchen, die mit "These" beginnt.
  • Da jede Zelle ein Leerzeichen gefolgt von dem Wert enthält, müssen wir den Abstand um den Wert verringern, da andernfalls die Verkettung fehlschlägt. Der Teil mit dem lmap Befehl behebt, dass
  • Always brace your expressions

Dokumentation: + (operator), - (operator), < (operator), chan, close, concat, csv (package), expr, for, format, incr, lassign, lindex, lmap (for Tcl 8.5), lmap, open, package, puts, set, struct::matrix (package), {*} (syntax)

+0

Danke Peter! Das funktioniert perfekt für dieses Beispielproblem! Als ich jedoch versuchte, es auf meine eigentliche CSV-Datei anzuwenden, bekam ich ein Problem. Ich habe mich gefragt, ob es irgendeinen Weg gibt, diese Datendatei mit dir zu teilen, damit du verstehen kannst, worum es mir geht? Im Grunde enthält meine Datendatei ein paar verschiedene Sätze von Matrix mit verschiedenen m * n und ich suche nach spezifischen Daten ähnlich denen, die ich als Beispiel in meinem früheren Beitrag gegeben habe, den Sie beantwortet haben! Danke für deine Hilfe Peter! – Reza

+0

@Reza: Können Sie die Datei irgendwo posten? Ich habe keine praktische Möglichkeit, Dateien zu empfangen (mein Sohn könnte wahrscheinlich etwas einrichten, aber er arbeitet). –

+0

Bitte laden Sie es über diesen Link (https://www.dropbox.com/s/li2ghbzrhd1ngxv/_SearchResults.csv?dl=0) Bitte lassen Sie mich wissen, wenn Sie nicht können? Grundsätzlich möchte ich nur die Zeilen unter "Horizontal-1 Acc. Dateiname und Horizontal-2 Acc. Dateiname" einzeln nachlesen! – Reza

0

wischen alle

package require csv 
package require struct::matrix 

::struct::matrix m 
m add columns 2 

set chan [open _SearchResults.csv] 
::csv::read2matrix $chan m , auto 
close $chan 

set f1 [m search column 0 {Result ID}] 
set headerRow [lindex $f1 0 1] 

set f2 [m search rect 0 $headerRow 0 [expr {[m rows] - 1}] {}] 
set numofRow [lindex [lindex $f2 0 1]] 

set headercol1 [m search row $headerRow { Horizontal-1 Acc. Filename}] 
set headercol2 [m search row $headerRow { Horizontal-2 Acc. Filename}] 

set indexheaderH1col [lindex $headercol1 0 0] 
set indexheaderH2col [lindex $headercol2 0 0] 

set header1 [m get cell $indexheaderH1col $headerRow] 
set header2 [m get cell $indexheaderH2col $headerRow] 

for {set r [expr $headerRow+1]} {$r < [expr $numofRow-1]} {incr r} { 
    puts [format {%-30s %s} [m get cell $indexheaderH1col $r] [m get cell $indexheaderH2col $r]] 
} 

set vector [concat {*}[m get rect $indexheaderH1col [expr $headerRow+1] $indexheaderH2col [expr $numofRow-1]]] 

puts [format {Vector=[ %s ]} [concat {*}[m get rect $indexheaderH1col [expr $headerRow+1] $indexheaderH2col [expr $numofRow-1]]]]