8

UCI機械学習データベースからの次のlispファイルがあります。Pythonを使用してフラットテキストファイルに変換したいと思います。典型的な行は次のようになります。

(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モジュールはありますか?Lispを見るのはこれが初めてです。

4

4 に答える 4

23

この回答に示されているように、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 | ピッチ| 期間| フェルマータ|
+ ========= + ======== + ==== + ======= + ===== + ========= +
| 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])
于 2012-12-27T18:21:08.217 に答える
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 ...
于 2012-12-27T20:15:16.987 に答える
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]

適切なフォーマットは、読者の練習問題として残されています...

于 2012-12-27T18:24:31.643 に答える
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)))
于 2016-04-19T02:39:39.163 に答える