WadokuJT-Datensätze extrahieren mit Ruby II
In meinem letzten Post habe ich beschrieben, wie ich die Originaldatensätze des Wadoku-Wörterbuchs von Dr. Ulrich Apel extrahiert habe. Leider war das Ergebnis, was daraus kam, nicht ganz das, was sich mein Auftraggeber wünschte.
Zur Erinnerung: so sah mein Ergebnis aus:
1655423 あ [1]; ア あ [1] <TrE: <HW n: a>> 1655423 あ [1]; ア あ [1] <TrE: <HW n: A>> 1655423 あ [1]; ア あ [1] <TrE: <HW m: Vokal> „<Topic: a>“> 1655423 あ [1]; ア あ [1] <TrE: <HW m: Lautwert> „<Topic: a>“>> 1655423 あ [1]; ア あ [1] <TrE: <HW m: Lautwert> „<Topic: a>“ in der 50-Laute-Tafel> 1655423 あ [1]; ア あ [1] <TrE: erstes <HW n: Zeichen> der ersten Reihe der 50-Laute-Tafel> 1655423 あ [1]; ア あ [1] <TrE: 36. <HW n: Zeichen> des Iroha-Gedichtes> 1655423 あ [1]; ア あ [1] <TrE: <HW n: Hiragana> „<Topic: a>“> 1655423 あ [1]; ア あ [1] <TrE: <Jap.: あ>> 1655423 あ [1]; ア あ [1] <TrE: <HW n: Katakana> „<Topic: a>“> 1655423 あ [1]; ア あ [1] <TrE: <Jap.: ア>>
Also schematisch gesehen
ID \t Schreibung 1; Schreibung 2; Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 1; Schreibung 2; Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 1; Schreibung 2; Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n
Das gewünschte Ergebnis sollte aber wie folgt ausehen:
ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n
Der Unterschied besteht darin, dass in meiner Version, die Schreibung1,2,3 nicht getrennt waren, was aber gewünscht wurde. Also musste ich mir was neues einfallen lassen.
Mein erster Gedanke war, dass ich auf die aktuelle „falsche“ Datei „wdk_list2“ korrigieren könnte, indem ich den zweiten Teil(im Array) jedes Eintrags spalte und den Rest(ID, Lesung und TrE) einfach jeweils wieder in der richtigen Reihenfolge dranhänge.
["ID", "Schreibung1;Schreibung2;Schreibung3", "Lesung in Kana", "TrE"] => [["ID", "Schreibung1", "Lesung in Kana", "TrE"] ["ID", "Schreibung2", "Lesung in Kana", "TrE"] ["ID", "Schreibung3", "Lesung in Kana", "TrE"]]
Also habe ich zunächst eine Methode geschrieben, die mir in einem Eintrag die verschiedenen Schreibungen trennt und als Array zurückgibt.
"ID \t Schreibung 1; Schreibung 2; Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 1" => ["ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 1", "ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 1", "ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 1"]
#seperate writing for an entry def sep_w entry rest = entry.split("\t").values_at(0,2,3) writing = entry.split("\t")[1].scan(/([^;\(\)\ 1-9\[\]\s]+)/).flatten #Der Regex /([^;\(\)\ 1-9\[\]\s]+)/ matcht alles außer ;,(,),[,],1-9 und \s white-space character in mehrfacher Ausführung acc = [] puts writing #um zu sehen ob das programm richtig tut writing.each{|w| acc = acc << rest.myinsert(1, w.strip).join("\t")} #myinsert gibt ein Duplikat vom Anfangsarray zurück return acc end
Dabei ist mir aufgefallen, dass die Methode „insert“ für die Klasse Array das eigentliche Objekt verändert, was ich in diesem Fall nicht gebrauchen kann.
Bsp:
ruby-1.9.2-p180 :207 > a = [1,3] => [1, 3] ruby-1.9.2-p180 :208 > a.insert(1,2) => [1, 2, 3] ruby-1.9.2-p180 :209 > a => [1, 2, 3] # #ich hätte aber gerne a unverändert # ruby-1.9.2-p180 :207 > a = [1,3] => [1, 3] ruby-1.9.2-p180 :208 > a.myinsert(1,2) => [1, 2, 3] ruby-1.9.2-p180 :209 > a => [1, 3]
Also musste ich noch eine eigene „insert“-Methode für die Klasse Array schreiben(„my_ultra_sexy_insert(pos, el)“…;D).
class Array def myinsert(pos, el) self.dup.insert(pos, el) end end
Als das getan war, probierte ich die Methode an einigen Einträgen aus der „wdk_list2“-Datei aus. Das Ergebnis war nicht ganz zufriedenstellend, denn die Reihenfolge der Schreibungen war falsch.
Statt der gewünschten Reihenfolge:
ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n
kam dabei raus:
ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 1 \n ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 2 \n ID \t Schreibung 1 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n ID \t Schreibung 2 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n ID \t Schreibung 3 \t Lesung in Kana \t Übersetzungsäquivalent 3 \n
Das Problem lag daran, dass als ich die Datei „wdk_list2“ aus „wdk_list“ generiert habe, ich zunächst die Übersetzungsäquivalente getrennt habe. Folglich müsste ich die „generate2“-Methode so modifizieren, dass zunächst die Schreibungen getrennt werden und dann die Übersetzungsäquivalente.
Die alte „generate2“-Methode sieht so aus:
def generate2 wdk content = File.open(wdk, "r").readlines #hier kann ich die neue Methode sep_w einbauen new_content = content.map do |entry| #der vordere Teil mit "wadoku_id", "writing", "midashigo" oder "kana" pre = entry.split("\t").values_at(0,1,2).join("\t") #die TrEs zusammengefasst in Array tre_array = parse(entry.split("\t")[3]) #pre + tre tre_array.map{|tre| pre + "\t" + tre}.join("\n") end #das ganze wird in die neue Datei "wdk_list2" reingeschrieben file = File.new("wdk_list2", "w") file.puts new_content file.close end
Die neu geschriebene Methode „sep_w“ wird hinzugefügt:
def generate2 wdk content = File.open(wdk, "r").readlines.map{|l| sep_w l}.flatten #aus einem verschachtelten Array wird ein Array new_content = content.map do |entry| pre = entry.split("\t").values_at(0,1,2).join("\t") tre_array = parse(entry.split("\t")[3]) tre_array.map do |tre| n_tre = tre.end_with?(">") ? tre : tre + ">" pre + "\t" + n_tre end.join("\n") end file = File.new("wdk_list2", "w") file.puts new_content file.close end
Daraufhin habe ich noch einmal die Methode „generate2“ mit der alten Datei „wdk_list“(nicht wdk_list2!, die ist ja schon modifiziert worden) ausgeführt.
Diesmal war das Ergebnis wesentlich besser anzusehen:
9110017 手いけ ていけ <TrE: <Def.: <HW n: Gestalten> seines eigenen Blumenarrangements>> 9110017 手いけ ていけ <TrE: (<Usage: übertr.>) <Def.: <HW m: Freikauf> einer Geisha, um sie zur Geliebten oder Ehefrau zu machen>> 9110017 手活け ていけ <TrE: <Def.: <HW n: Gestalten> seines eigenen Blumenarrangements>> 9110017 手活け ていけ <TrE: (<Usage: übertr.>) <Def.: <HW m: Freikauf> einer Geisha, um sie zur Geliebten oder Ehefrau zu machen>> 9110017 手活 ていけ <TrE: <Def.: <HW n: Gestalten> seines eigenen Blumenarrangements>> 9110017 手活 ていけ <TrE: (<Usage: übertr.>) <Def.: <HW m: Freikauf> einer Geisha, um sie zur Geliebten oder Ehefrau zu machen>> 9110017 手生け ていけ <TrE: <Def.: <HW n: Gestalten> seines eigenen Blumenarrangements>> 9110017 手生け ていけ <TrE: (<Usage: übertr.>) <Def.: <HW m: Freikauf> einer Geisha, um sie zur Geliebten oder Ehefrau zu machen>> 9110017 手生 ていけ <TrE: <Def.: <HW n: Gestalten> seines eigenen Blumenarrangements>> 9110017 手生 ていけ <TrE: (<Usage: übertr.>) <Def.: <HW m: Freikauf> einer Geisha, um sie zur Geliebten oder Ehefrau zu machen>>
Achja…nachdem ich die Datei generiert hatte, musste ich noch die bekannte „kill_n“-Methode ausführen, damit die überflüssigen „\n“ schön brav „weggeblieben“ werden.
Obwohl diese Version im Vergleich zu den anderen richtiger aussieht, habe ich trotzdem einige Einträge gefunden, die fehlerhaft angezeigt werden z.B:
7198845 泥砂 でいしゃ <TrE: <HW m: Schlamm> und <HW m: Sand>> 7198845 b でいしゃ <TrE: <HW m: Schlamm> und <HW m: Sand>> 7198845 泥沙 でいしゃ <TrE: <HW m: Schlamm> und <HW m: Sand>>
oder
5885835 出かけ でかけ <TrE: <HW m: Aufbruch> 5885835 出かけ でかけ <TrE: <HW n: Fortgehen>> 5885835 出掛け でかけ <TrE: <HW m: Aufbruch> 5885835 出掛け でかけ <TrE: <HW n: Fortgehen>> 5885835 a でかけ <TrE: <HW m: Aufbruch> 5885835 a でかけ <TrE: <HW n: Fortgehen>> 5885835 出掛 でかけ <TrE: <HW m: Aufbruch> 5885835 出掛 でかけ <TrE: <HW n: Fortgehen>> 5885835 でかけ でかけ <TrE: <HW m: Aufbruch> 5885835 でかけ でかけ <TrE: <HW n: Fortgehen>> 4371129 出掛け でがけ <TrE: <HW m: Aufbruch> 4371129 出掛け でがけ <TrE: <HW m: Zeitpunkt>, wenn man weggeht> 4371129 出掛け でがけ <TrE: <HW m: Zeitpunkt>, gleich nach dem Aufbruch> 4371129 b でがけ <TrE: <HW m: Aufbruch> 4371129 b でがけ <TrE: <HW m: Zeitpunkt>, wenn man weggeht> 4371129 b でがけ <TrE: <HW m: Zeitpunkt>, gleich nach dem Aufbruch> 4371129 出がけ でがけ <TrE: <HW m: Aufbruch> 4371129 出がけ でがけ <TrE: <HW m: Zeitpunkt>, wenn man weggeht> 4371129 出がけ でがけ <TrE: <HW m: Zeitpunkt>, gleich nach dem Aufbruch> 4371129 出掛 でがけ <TrE: <HW m: Aufbruch> 4371129 出掛 でがけ <TrE: <HW m: Zeitpunkt>, wenn man weggeht> 4371129 出掛 でがけ <TrE: <HW m: Zeitpunkt>, gleich nach dem Aufbruch> 4371129 でがけ でがけ <TrE: <HW m: Aufbruch> 4371129 でがけ でがけ <TrE: <HW m: Zeitpunkt>, wenn man weggeht> 4371129 でがけ でがけ <TrE: <HW m: Zeitpunkt>, gleich nach dem Aufbruch>
Die Einträge mit nur „a“ oder „b“ als Schreibung kommen daher, da es auch Einträge gibt mit Buchstaben-Indexe, die so aussehen:
5885835 出かけ; 出掛け [a]; 出掛; でかけ... 4371129 出掛け [b]; 出がけ; 出掛; でがけ...
Mein Regex hat zwar Zahlen 1-9 in eckigen Klammern rausgefiltert, aber die westlichen Buchstaben sind nicht davon betroffen.
/([^;\(\)\ 1-9\[\]\s]+)/
Das heißt: to be continued… …ó__ò