2012-12-27 13 views
6

私はUCI machine learning databaseの以下のlispファイルを持っています。私はそれをPythonを使ってフラットテキストファイルに変換したいと思います。典型的な行は次のようになります。Pythonでlispファイルを解析する

(1 ((st 8) (pitch 67) (dur 4) (keysig 1) (timesig 12) (fermata 0))((st 12) (pitch 67) (dur 8) (keysig 1) (timesig 12) (fermata 0))) 

私のようなテキストファイルにこれを解析したいと思います:

time pitch duration keysig timesig fermata 
8 67 4  1  12  0 
12 67 8  1  12  0 

インテリジェントこれを解析するためのpythonモジュールはありますか?これは初めてのことです。

+0

ん[Pythonで解析S-式](http://stackoverflow.com/q/3182594)を助けますか? –

+0

ありがとう、見てみましょう。 – qua

+1

lispを使って別の形式に変換してみませんか? – Marcin

答えて

20

this answerに示すように、pyparsingは、そのための適切なツールであると思われる:

inputdata = '(1 ((st 8) (pitch 67) (dur 4) (keysig 1) (timesig 12) (fermata 0))((st 12) (pitch 67) (dur 8) (keysig 1) (timesig 12) (fermata 0)))' 

from pyparsing import OneOrMore, nestedExpr 

data = OneOrMore(nestedExpr()).parseString(inputdata) 
print data 

# [['1', [['st', '8'], ['pitch', '67'], ['dur', '4'], ['keysig', '1'], ['timesig', '12'], ['fermata', '0']], [['st', '12'], ['pitch', '67'], ['dur', '8'], ['keysig', '1'], ['timesig', '12'], ['fermata', '0']]]] 

完全ために、これは(texttableを使用)、結果をフォーマットする方法である:

from texttable import Texttable 

tab = Texttable() 
for row in data.asList()[0][1:]: 
    row = dict(row) 
    tab.header(row.keys()) 
    tab.add_row(row.values()) 
print tab.draw() 
 
+---------+--------+----+-------+-----+---------+ 
| timesig | keysig | st | pitch | dur | fermata | 
+=========+========+====+=======+=====+=========+ 
| 12  | 1  | 8 | 67 | 4 | 0  | 
+---------+--------+----+-------+-----+---------+ 
| 12  | 1  | 12 | 67 | 8 | 0  | 
+---------+--------+----+-------+-----+---------+ 

このデータをlisp表記に変換するには:

def lisp(x): 
    return '(%s)' % ' '.join(lisp(y) for y in x) if isinstance(x, list) else x 

d = lisp(d[0]) 
+0

Opは "Python *モジュール*を知的に*解析する"という質問に対して、これは間違いなく答えです – Bakuriu

+0

ありがとう!本当に役に立ちました。 – qua

+0

どのようにデータをLispコードに変換すればよいですか? –

1

正規表現とペアに分離:

In [1]: import re 

In [2]: txt = '(((st 8) (pitch 67) (dur 4) (keysig 1) (timesig 12) (fermata 0))((st 12) (pitch 67) (dur 8) (keysig 1) (timesig 12) (fermata 0)))' 

In [3]: [p.split() for p in re.findall('\w+\s+\d+', txt)] 
Out[3]: [['st', '8'], ['pitch', '67'], ['dur', '4'], ['keysig', '1'], ['timesig', '12'], ['fermata', '0'], ['st', '12'], ['pitch', '67'], ['dur', '8'], ['keysig', '1'], ['timesig', '12'], ['fermata', '0']] 
その後

辞書にそれを作る:

dct = {} 
for p in data: 
    if not p[0] in dct.keys(): 
     dct[p[0]] = [p[1]] 
    else: 
     dct[p[0]].append(p[1]) 

結果:

In [10]: dct 
Out[10]: {'timesig': ['12', '12'], 'keysig': ['1', '1'], 'st': ['8', '12'], 'pitch': ['67', '67'], 'dur': ['4', '8'], 'fermata': ['0', '0']} 

印刷:

print 'time pitch duration keysig timesig fermata' 
for t in range(len(dct['st'])): 
    print dct['st'][t], dct['pitch'][t], dct['dur'][t], 
    print dct['keysig'][t], dct['timesig'][t], dct['fermata'][t] 
あなたはデータが正しいとあなたはこのデータとドンが必要な場合は、フォーマットの制服は(一見そう思える)、およびことがわかっている場合

適切なフォーマットが...読者の練習として

2

を残しています一般的な問題を解決する必要はありません。それでは、数字以外のすべての数字をスペースで置き換えてから分割するのはなぜですか?

import re 
data = open("chorales.lisp").read().split("\n") 
data = [re.sub("[^-0-9]+", " ", x) for x in data] 
for L in data: 
    L = map(int, L.split()) 
    i = 1 # first element is chorale number 
    while i < len(L): 
     st, pitch, dur, keysig, timesig, fermata = L[i:i+6] 
     i += 6 
     ... your processing goes here ... 
1

データがLispで既にあるので、Lispの自分自身を使用します。

(let ((input '(1 ((ST 8) (PITCH 67) (DUR 4) (KEYSIG 1) (TIMESIG 12) (FERMATA 0)) 
      ((ST 12) (PITCH 67) (DUR 8) (KEYSIG 1) (TIMESIG 12) (FERMATA 0))))) 

     (let ((row-headers (mapcar 'car (second input))) 
      (row-data (mapcar (lambda (row) (mapcar 'second row)) (cdr input)))) 

    (format t "~{~A~^ ~}~%" row-headers) 
    (format t "~{~{~A~^ ~}~^ ~%~}" row-data))) 
関連する問題