2016-10-04 3 views
0

Ich habe eine DateiCount Anzahl der Wörter spezifischer Typ

 
Anny : dancing 
Sonny : reciting 
Joel : dancing 
Anny : reciting 
Anny : singing 

folgenden Daten möchte ich folgendes o/p in tcl:

 
Anny - 
singing 1 
dancing 1 
reciting 1 

Joel - 
dancing 1 

Ich möchte in diesem Format drucken, zusammen mit ihre Zählung.

+0

Wo ist dein Problem? –

+0

Ich versuchte es mit llength [regexp -all tanzend Anny], aber es scheint nicht zu funktionieren. Es passt entweder einmal oder gar nicht. Ich habe Dutzende ähnlicher Vorkommen, aber die Anzahl ist falsch – johnny

+0

Wie nicht verstehen, wie Ihre Regexp übereinstimmen könnte. –

Antwort

1

mit Donals Antwort Arbeiten, aber ein einziges Wörterbuch anstelle eines Arrays von Wörterbüchern mit:

set data [dict create] 

set f [open yourinputfile.txt r] 
while {[gets $f line] != -1} { 
    if {[scan $line "%s : %s" who what] == 2} { 
     dict update data $who activities { 
      dict incr activities $what 
     } 
    } 
} 
close $f 

dict for {who activities} $data { 
    puts "$who -" 
    dict for {what count} $activities { 
     puts "$what $count" 
    } 
    puts "" 
} 
+0

@donal, gibt es einen Grund, warum 'dict incr' nicht wie' dict incr dictionaryVariable key? Key ... angegeben wurde? "increment?" - war es die Zweideutigkeit darüber, ob das letzte Argument ein Schlüssel oder ein Inkrement ist? –

+0

Schön. Danke für das Zeigen, dass ich die 'Diktatupdate' Dokumentation die ganze Zeit falsch gelesen habe;) –

+0

@glenn .. Danke für mich gearbeitet !! Ich versuchte mit lsort -creasing $ count, um die Liste in absteigender Reihenfolge zu erhalten, aber es scheint nicht zu funktionieren .. ist es nicht gültig, in diesem Fall lsort zu verwenden ?? – johnny

0

Sie könnten ein Array verwenden, um die Informationen zu speichern, während Sie in sind zu sammeln.

Die regexp Sie verwenden falsch ist.

Verwenden Sie eine Liste von Listen, um die Übereinstimmung paarweise zu sammeln (z. B. Wort #n), und weisen Sie dann alle gesammelten Übereinstimmungen dem richtigen Schlüssel im Array zu. Hier

ist ein Beispiel, wie man es tun:

set file_content {Anny : dancing 
Sonny : reciting 
Joel : dancing 
Anny : reciting 
Anny : singing 
} 

array set res {} 

set anny {} 

lappend anny [list dancing [regexp -all {Anny\s*:\s*dancing} $file_content] ] 
lappend anny [list singing [regexp -all {Anny\s*:\s*singing} $file_content] ] 
lappend anny [list reciting [regexp -all {Anny\s*:\s*reciting} $file_content] ] 

set res(Anny) $anny 

puts [array get res] 

Wenn ich diese laufen die Ausgabe lautet:

Anny {{dancing 1} {singing 1} {reciting 1}} 

Nun könnte man das Array verwenden, um die Ausgabe zu formatieren wie du möchtest.

Natürlich sollten Sie das gleiche mit anderen Namen tun, so ist das Beste, den Code in eine Funktion zu setzen.

+1

Es scheint mir, dass Sie den Punkt vermissen: Sie sollten die Datei analysieren, nicht alle Namen und Aktivitäten in Ihrem Code hart codieren. –

1

Dies ist wirklich über das Zählen Worte, so werden wir mit Wörterbüchern zu tun haben - dict incr ein perfektes Werkzeug hierfür ist - aber Sie müssen auch ein bisschen Analyse tun. Parsen ist auf viele Arten gemacht, aber in diesem Fall kann tun, was wir leicht wollen. (Denken Sie daran, wenn mein Code zu lesen, dass die Ergebnis von scan ist die Anzahl der Felder, die es geschafft zu befriedigen.)

set f [open "yourinputfile.txt"] 
set data [split [read $f] "\n"] 
close $f 

# Peel apart that data 
foreach line $data { 
    if {[scan $line "%s : %s" who what] == 2} { 
     dict incr activity($who) $what 
    } 
} 

# Now produce the output 
foreach who [lsort [array names activity]] { 
    puts "$who -" 
    dict for {what count} $activity($who) { 
     puts "$what $count" 
    } 
    # And the extra blank line 
    puts "" 
} 
+0

perfekte Lösung – johnny

+0

Hallo Ich habe versucht, den oben genannten Code und es funktioniert gut zum ersten Mal, aber wenn ich es erneut ausgeführt wurde der Wert inkrementiert zweimal .i.e Hinzufügen zu seinem vorherigen Wert. Gibt es ein solches Problem, das Ihnen auch – johnny

+0

der Befehl dict für .. ist nicht funktioniert für mich, gibt es mir iterativen Wert bei 1. und dann der tatsächliche Wert – johnny

0

Dieser Weg ist, es zu tun.

Die Anzahl der verschiedenen Zeilen zählen. Beseitigen Sie den Doppelpunkt.

Konvertieren Sie das Wörterbuch von Zeilen und Zählern in ein hierarchisches Wörterbuch mit Namen auf der höchsten Ebene und Aktivitäten auf der nächsten Ebene. Wenn line "Joel dancing" enthält, wird der folgende Aufruf nach der Erweiterung mit {*}: dict set d1 Joel dancing 1 zum Erstellen des Wörterbuchelements Joel {dancing 1}.

dict for {line count} $d0 { 
    dict set d1 {*}$line $count 
} 

Iterieren Sie über das Wörterbuch und drucken Sie die Schlüssel und Werte.

dict for {name activities} $d1 { 
    puts "$name -" 
    foreach {activity count} $activities { 
     puts "$activity $count" 
    } 
    puts {} 
} 

Dokumentation: dict, foreach, puts, split, string, {*} (syntax)

Verwandte Themen