我最近开始使用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']。数据[2]然后。
我没有想法 - 是否可以通过一些简单的方式加入结果,或者我需要使用其他功能更改ParseResults?
感谢您的帮助。
BTW - 这个代码在解析日期,数量等方面是否合理?答案 0 :(得分:1)
这种表格数据的解析是编写pyparsing的原始案例之一。恭喜您解析了一个非平凡的输入文本!
我没有尝试做任何不自然的分组或者什么来将解析后的数据扭曲或组合到你想要的数据结构中,而是在你得到它们的时候走完解析后的结果并建立一个新的汇总结构,我我会打电话给summary
。我们实际上会将数据累积到这个dict中,强烈建议在找到新密钥时使用defaultdict简化摘要初始化。
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')}