加入pyparsing结果

时间:2013-06-07 11:11:49

标签: pyparsing

我最近开始使用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 - 这个代码在解析日期,数量等方面是否合理?

1 个答案:

答案 0 :(得分:1)

这种表格数据的解析是编写pyparsing的原始案例之一。恭喜您解析了一个非平凡的输入文本!

我没有尝试做任何不自然的分组或者什么来将解析后的数据扭曲或组合到你想要的数据结构中,而是在你得到它们的时候走完解析后的结果并建立一个新的汇总结构,我我会打电话给summary。我们实际上会将数据累积到这个dict中,强烈建议在找到新密钥时使用defaultdict简化摘要初始化。

from collections import defaultdict
summary = defaultdict(dict)

查看p中返回的当前结构,您将获得收集到命名结果itdetails中的项目标题和详细数据集。我们可以将这些压缩在一起以获取每个部分的标题和数据。然后,对于细节中的每一行,我们将通过使用解析的数据值压缩项目标题来制作详细值的字典。然后,我们将更新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')}