Zum Inhalt springen

WadokuJT-Datensätze extrahieren mit Ruby II

15/09/2011

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… …ó__ò

From → Programmierung

Kommentar verfassen

Hinterlasse einen Kommentar