2016-12-05 2 views
0

Ich habe eine Text-Datei mit folgendem Format verschmelzenden:Python: Wörterbücher mit Werten hinzugefügt, aber die Erhaltung anderen Bereichen

word_form root_form morphological_form frequency 
word_form root_form morphological_form frequency 
word_form root_form morphological_form frequency 

... mit 1 Million Artikel

Aber einige der word_forms enthalten einen Apostroph (‚), andere nicht, so würde ich sie als Instanzen des gleichen Wortes zählen möchte, ist zu sagen, dass ich Zeilen möchte wie diese beiden verschmelzen:

cup'board cup  blabla 12 
cupboard cup  blabla2 10 

in diese ein (Frequenzen hinzugefügt):

cupboard cup  blabla2 22 

Ich bin eine Lösung in Python 2.7 die Suche zu tun, meine erste Idee, den Text-Datei, Speichern in zwei verschiedene Wörterbücher Wörter mit Apostroph und die Worte ohne, dann gehen Sie über das Wörterbuch von Wörtern zu lesen war mit Apostroph, prüfen Sie, ob diese Wörter bereits im Wörterbuch ohne Apostroph sind, ob sie die Häufigkeit aktualisieren, oder fügen Sie einfach diese Zeile mit entferntem Apostroph hinzu. Hier ist mein Code:

class Lemma: 
    """Creates a Lemma with the word form, the root, the morphological analysis and the frequency in the corpus""" 
    def __init__(self,lop): 
     self.word_form = lop[0] 
     self.root = lop[1] 
     self.morph = lop[2] 
     self.freq = int(lop[3]) 

def Reader(filename): 
    """Keeps the lines of a file in memory for a single reading, memory efficient""" 
    with open(filename) as f: 
     for line in f: 
      yield line 

def get_word_dict(filename): 
    '''Separates the word list into two dictionaries, one for words with apostrophe and one for words with apostrophe''' 
    '''Works in a reasonable time''' 
    '''This step can be done writing line by line, avoiding all storage in memory''' 
    word_dict = {} 
    word_dict_striped = {} 

    # We store the lemmas in two dictionaries, word_dict for words without apostrophe, word_dict_striped for words with apostrophe 
    with open('word_dict.txt', 'wb') as f: 
     with open('word_dict_striped.txt', 'wb') as g: 

      reader = Reader(filename) 
      for line in reader: 
       items = line.split("\t") 
       word_form = items[0] 
       if "'" in word_form: 
        # we remove the apostrophe in the word form and morphological analysis and add the lemma to the dictionary word_dict_striped 
        items[0] = word_form.replace("'","") 
        items[2] = items[2].replace("\+Apos", "") 

        g.write("%s\t%s\t%s\t%s" % (items[0], items[1], items[2], items[3])) 
        word_dict_striped({items[0] : Lemma(items)}) 
       else: 
        # we just add the lemma to the dictionary word_dict 
        f.write("%s\t%s\t%s\t%s" % (items[0], items[1], items[2], items[3])) 
        word_dict.update({items[0] : Lemma(items)}) 

    return word_dict, word_dict_striped 

def merge_word_dict(word_dict, word_dict_striped): 
    '''Takes two dictionaries and merge them by adding the count of their frequencies if there is a common key''' 
    ''' Does not run in reasonable time on the whole list ''' 

    with open('word_compiled_dict.txt', 'wb') as f: 

     for word in word_dict_striped.keys(): 
      if word in word_dict.keys(): 
       word_dict[word].freq += word_dict_striped[word].freq 
       f.write("%s\t%s\t%s\t%s" % (word_dict[word].word_form, word_dict[word].root, word_dict[word].morph, word_dict[word].freq)) 
      else: 
       word_dict.update(word_dict_striped[word]) 

    print "Number of words: ", 
    print(len(word_dict)) 

    for x in word_dict: 
     print x, word_dict[x].root, word_dict[x].morph, word_dict[x].freq 

    return word_dict 

Diese Lösung funktioniert in einer angemessenen Zeit, bis die Speicherung der zwei Wörterbücher, ob ich in zwei Text-Dateien Zeile für Zeile schreibe jede Lagerung zu vermeiden oder speichere ich sie als dict Objekte im Programm . Aber das Verschmelzen der beiden Wörterbücher endet nie!

Die Funktion 'update' für Wörterbücher funktioniert, überschreibt jedoch eine Häufigkeitszählung anstelle der beiden. Ich sah einige Lösungen der Verschmelzung Wörterbücher mit zusätzlich mit Counter: Python: Elegantly merge dictionaries with sum() of values Merge and sum of two dictionaries How to sum dict elements How to merge two Python dictionaries in a single expression? Is there any pythonic way to combine two dicts (adding values for keys that appear in both)? aber sie scheinen nur zu arbeiten, wenn die Wörterbücher der Form sind (Wort, zählen), während ich die anderen Felder tragen möchten auch im Wörterbuch.

Ich bin offen für alle Ihre Ideen oder Reframing des Problems, da mein Ziel ist, dieses Programm nur einmal auszuführen, um diese zusammengeführte Liste in einer Textdatei zu erhalten, danke im Voraus!

+0

Können Sie nicht einfach alle Apostrophe durch eine leere Zeichenfolge ersetzen, um sie zu entfernen? Wie folgt: 'word_form = items [0] .replace (''", "") ' –

+0

Aber dann habe ich zwei Zeilen mit demselben Wort und diese Frequenzen werden nicht hinzugefügt, oder? – hajoki

+0

Gibt es höchstens zwei Zeilen, die für ein bestimmtes Wort oder möglicherweise mehr kombiniert werden können? Sind diejenigen, die notwendigerweise miteinander kombiniert werden müssen? Wenn zwei Linien kombiniert werden sollen, ist alles andere (abgesehen von den Zählungen) garantiert dasselbe? – Iluvatar

Antwort

0

Hier ist etwas, das mehr oder weniger was Sie wollen. Ändern Sie einfach die Dateinamen oben. Es ändert die ursprüngliche Datei nicht.

input_file_name = "input.txt" 
output_file_name = "output.txt" 

def custom_comp(s1, s2): 
    word1 = s1.split()[0] 
    word2 = s2.split()[0] 
    stripped1 = word1.translate(None, "'") 
    stripped2 = word2.translate(None, "'") 

    if stripped1 > stripped2: 
     return 1 
    elif stripped1 < stripped2: 
     return -1 
    else: 
     if "'" in word1: 
      return -1 
     else: 
      return 1 

def get_word(line): 
    return line.split()[0].translate(None, "'") 

def get_num(line): 
    return int(line.split()[-1]) 

print "Reading file and sorting..." 

lines = [] 
with open(input_file_name, 'r') as f: 
    for line in sorted(f, cmp=custom_comp): 
     lines.append(line) 

print "File read and sorted" 

combined_lines = [] 

print "Combining entries..." 

i = 0 
while i < len(lines) - 1: 
    if get_word(lines[i]) == get_word(lines[i+1]): 
     total = get_num(lines[i]) + get_num(lines[i+1]) 
     new_parts = lines[i+1].split() 
     new_parts[-1] = str(total) 
     combined_lines.append(" ".join(new_parts)) 
     i += 2 
    else: 
     combined_lines.append(lines[i].strip()) 
     i += 1 

print "Entries combined" 
print "Writing to file..." 

with open(output_file_name, 'w+') as f: 
    for line in combined_lines: 
     f.write(line + "\n") 

print "Finished" 

Es sortiert die Worte und vermasselt die ein wenig Abstand. Wenn das wichtig ist, lass es mich wissen und es kann angepasst werden.

Eine andere Sache ist, dass es die ganze Sache sortiert. Für nur eine Million Zeilen wird das wahrscheinlich nicht lange dauern, aber lassen Sie mich wissen, ob das ein Problem ist.

+0

Vielen Dank für Ihre Antwort, die in weniger als einer Minute dreht! Ich änderte es ein wenig, um den Eintrag auch ohne Apostroph einfügen zu lassen, auch wenn es keinen Eintrag mit Apostroph gibt, mit dem ich verschmelzen konnte, und mir wurde klar, dass ich das Programm mehrmals ausführen musste, weil es mehr als zwei Zeilen gibt. mein Schlechter, ich wusste nicht, dass es war), aber ein Programm zu haben, das alles ändert, ändert sich! – hajoki

Verwandte Themen