我最近开始使用pyparsing,我坚持如下:有一些数据是按列组织的,其中列的数量是未知的,另外,这样的部分在输入中可能会多次出现。请看下面的代码示例。
# -*- coding: utf-8 -*-
from pyparsing import *
from decimal import Decimal
def convert_float(a):
return Decimal(a[0].replace(',','.'))
def convert_int(a):
return int(a[0])
NL = LineEnd().suppress()
dot = Literal('.')
dates = Combine(Word(nums,exact=2) + dot + Word(nums,exact=2) + dot + Word(nums,exact=4))
day_with_date = Word(alphas,exact=3).suppress() + dates
amount = ( Combine(OneOrMore(Word(nums)) + ',' + Word(nums),adjacent=False) +
Optional(Literal('EUR')).suppress() ).setParseAction(convert_float)
number = Word(nums).setParseAction(convert_int)
item_head = OneOrMore(Keyword('Item').suppress() + number)
item_det = Forward()
item_foot = Forward()
def defineColNumber(t):
nbcols = len(t)#[0])
item_det << Dict(Group(day_with_date('date') + Group(nbcols*amount)('data')))
item_foot << Keyword('TOTAL').suppress() + Group(nbcols*amount)
sec = (item_head('it*').setParseAction(defineColNumber) +
Group(OneOrMore(item_det))('details*') +
item_foot('totals*'))
parser = OneOrMore(
sec
)
parser.ignore(NL)
out = """
Item 1 Item 2 Item 3
Sat 20.04.2013 3 126 375,00 EUR 115 297,00 EUR 67 830,00 EUR
Fri 19.04.2013 1 641 019,20 EUR 82 476,00 EUR 48 759,00 EUR
Thu 18.04.2013 548 481,10 EUR 46 383,00 EUR 29 810,00 EUR
Wed 17.04.2013 397 396,70 EUR 42 712,00 EUR 26 812,00 EUR
TOTAL 8 701 732,00 EUR 1 661 563,00 EUR 1 207 176,00 EUR
Item 4 Item 5
Sat 20.04.2013 126 375,00 EUR 215 297,00 EUR
Fri 19.04.2013 2 641 019,20 EUR 32 476,00 EUR
Thu 18.04.2013 548 481,10 EUR 56 383,00 EUR
Wed 17.04.2013 397 396,70 EUR 42 712,00 EUR
TOTAL 2 701 732,00 EUR 1 663 563,00 EUR
"""
p = parser.parseString(out, parseAll=True)
print p.dump()
print p.it
print p.details[0]['18.04.2013'].data[2]
print p.totals例如,目前p.it看起来像[[1, 2, 3], [4, 5]],对于其他部分,我也需要[1,2,3,4,5],所以我可以不使用p.details[0]['18.04.2013'].data[2],而使用p.details['18.04.2013'].data[2]。
我没有想法了--有没有可能以一种简单的方式连接结果,或者我需要用其他函数来改变ParseResults?
谢谢你的帮助。
顺便说一句,这段代码对解析日期、金额等有意义吗?
发布于 2013-06-07 20:49:38
这种对表格数据的解析是编写pyparsing的初衷之一。恭喜你在解析非平凡的输入文本方面走到了这一步!
我不会尝试进行任何不自然的分组,也不会尝试将解析后的数据扭曲或组合到您想要的数据结构中,我只需要遍历解析后的结果,然后构建一个新的摘要结构,我称之为summary。我们实际上要将数据累积到这个字典中,这强烈建议在找到新的关键字时使用默认字典来简化摘要的初始化。
from collections import defaultdict
summary = defaultdict(dict)查看p中返回的当前结构,您将获得收集到命名结果it和details中的项头和详细数据集。我们可以将它们压缩在一起,以获得每个部分的标题和数据。然后,对于详细信息中的每一行,我们将通过使用解析的数据值压缩项标题来创建详细值的字典。然后,我们将更新由line.date键入的汇总值
for items,details in zip(p.it,p.details):
for line in details:
summary[line.date[0]].update(dict(zip(items,line.data)))完成了!看看我们积累的关键字是什么:
print summary.keys()提供:
['20.04.2013', '18.04.2013', '17.04.2013', '19.04.2013']打印‘18.04.2013’的累计数据:
print summary['18.04.2013']提供:
{1: Decimal('548481.10'), 2: Decimal('46383.00'), 3: Decimal('29810.00'), 4: Decimal('548481.10'), 5: Decimal('56383.00')}https://stackoverflow.com/questions/16982712
复制相似问题