2016-07-29 30 views
0

Ich habe verschiedene Textdateien und ich möchte die Werte von dort in eine CSV-Datei extrahieren. Jede Datei hat folgendes FormatExtrahieren Sie Textdateien in mehrere Spalten in Python

main cost: 30 
additional cost: 5 

ich es geschafft, das zu tun, aber das Problem, dass ich es die Werte der einzelnen Datei in eine andere Spalten eingefügt werden soll Ich möchte auch die Anzahl von Textdateien ein Benutzer Argument sein

Das ist, was ich jetzt

numFiles = sys.argv[1] 
    d = [[] for x in xrange(numFiles+1)] 
    for i in range(numFiles): 
     filename = 'mytext' + str(i) + '.text' 
     with open(filename, 'r') as in_file: 
     for line in in_file: 
     items = line.split(' : ') 
     num = items[1].split('\n') 

     if i ==0: 
      d[i].append(items[0]) 

     d[i+1].append(num[0]) 

     grouped = itertools.izip(*d[i] * 1) 
     if i == 0: 
      grouped1 = itertools.izip(*d[i+1] * 1) 

     with open(outFilename, 'w') as out_file: 
      writer = csv.writer(out_file) 
      for j in range(numFiles): 
       for val in itertools.izip(d[j]): 
        writer.writerow(val) 

tun Dies ist, was ich jetzt immer, alles in einer Spalte

main cost 
additional cost 
30 
5 
40 
10 

Und ich will es

main cost  | 30 | 40 
additional cost | 5 | 10 
+0

haben Sie versucht Tupeln verwenden? –

+0

Woher kommt die letzte Spalte in der gewünschten Ausgabe? Sind in jeder Eingabedatei nur zwei Zeilen enthalten? – wwii

+0

ich die Eingabedatei unter der Annahme, sieht etwa so aus: Hauptkosten: 30 zusätzliche Kosten: 5 Hauptkosten: 40 zusätzliche Kosten: 10 – Michael

Antwort

2

sein Sie ein Wörterbuch verwenden könnte, dies zu tun, wo der Schlüssel ist die „Header“, die Sie verwenden möchten, und der Wert eine Liste sein.

So würde es aussehen someDict = {'main cost': [30,40], 'additional cost': [5,10]}

edit2: Wir gingen weiter und aufgeräumt diese Antwort, so dass es ein wenig mehr Sinn macht.

können Sie das Wörterbuch erstellen und über es wie folgt durchlaufen:

from collections import OrderedDict 

in_file = ['main cost : 30', 'additional cost : 5', 'main cost : 40', 'additional cost : 10'] 
someDict = OrderedDict() 

for line in in_file: 
    key,val = line.split(' : ') 
    num = int(val) 
    if key not in someDict: 
     someDict[key] = [] 

    someDict[key].append(num) 

for key in someDict: 
    print(key) 
    for value in someDict[key]: 
     print(value) 

Die Code-Ausgänge:

main cost 
30 
40 
additional cost 
5 
10 

sollte ziemlich einfach sein, um das Beispiel zu ändern, um Ihre gewünschte Ausgabe zu passen.

Ich habe das Beispiel @append multiple values for one key in Python dictionary und dank @wwii für einige Vorschläge verwendet.

Ich habe eine verwendet, da ein Wörterbuch die Schlüssel nicht in der Reihenfolge hält.

Sie können mein Beispiel @https://ideone.com/myN2ge

+0

Für diese Lösung können Sie sicher sein, dass es nur zwei Schlüssel gibt, so dass Sie das Wörterbuch mit diesen zwei Schlüsseln und einer leeren Liste für Werte vorher konstruieren konnten - dann können Sie das loswerden '' 'if/else''' für die Wörterbuchzuordnung. Alternativ können Sie, wenn Sie sich vorher nicht sicher über die Schlüssel sind, ['' 'collections.defaultdict'''] (https://docs.python.org/3/library/collections.html#collections.defaultdict) verwenden. – wwii

+1

Wenn Sie Text teilen und planen, die einzelnen Elemente später in Ihrem Code zu verwenden, ist es nett, ihnen Namen zu geben - dadurch wird der nachfolgende Code leichter lesbar. Nutzen Sie das Auspacken: in diesem Fall etwas wie - '' 'key, value = line.split (':'); value = value.strip() '' ' – wwii

+0

Beide großartige Beispiele. Zum einen würde ich es wahrscheinlich so halten, dass sich die Dateiformate in Zukunft ändern können, ohne den Code ändern zu müssen. Ich stimme deinem zweiten Beispiel zu. – Michael

0

Dies ist laufen, wie ich es tun könnte. Angenommen, die Felder sind in allen Dateien identisch. Erstellen Sie eine Liste von Namen und ein Wörterbuch, das diese Feldnamen als Schlüssel verwendet, und die Liste der Werte als Einträge. Anstatt auf file1.text, file2.text usw. zu laufen, führen Sie das Skript mit file*.text als Befehlszeilenargument aus.

#! /usr/bin/env python 

import sys 

if len(sys.argv)<2: 
    print "Give file names to process, with wildcards" 
else: 
    FileList= sys.argv[1:] 
    FileNum = 0 
    outFilename = "myoutput.dat" 
    NameList = [] 
    ValueDict = {} 
    for InfileName in FileList: 
     Infile = open(InfileName, 'rU') 
     for Line in Infile: 
      Line=Line.strip('\n') 
      Name,Value = Line.split(":") 
      if FileNum==0: 
       NameList.append(Name.strip()) 
      ValueDict[Name] = ValueDict.get(Name,[]) + [Value.strip()] 
     FileNum += 1 # the last statement in the file loop 
     Infile.close() 
    # print NameList 
    # print ValueDict 

    with open(outFilename, 'w') as out_file: 
     for N in NameList: 
      OutString = "{},{}\n".format(N,",".join(ValueDict.get(N))) 
      out_file.write(OutString) 

Ausgang für meine vier gefälschte Dateien war:

main cost,10,10,40,10 
additional cost,25.6,25.6,55.6,25.6 
+0

Danke @beroe, aber ich möchte die Ausgabe in einer CSV-Datei gespeichert werden und die '|' für eine andere Spalte – Lily

+0

Ändern Sie einfach die '| 'in den Code zu einem Komma ... – beroe

+0

das ist, was ich bekomme, wenn ich den obigen Code TypeError versuchen: kann nur eine iterable – Lily