【问题标题】:Joining pyparsing results加入 pyparsing 结果
【发布时间】:2013-06-07 11:11:49
【问题描述】:

我最近开始使用 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['18.04.2013'].data[2] 代替p.details[0]['18.04.2013'].data[2]

我没有想法 - 是否可以通过某种简单的方式加入结果,或者我需要使用其他功能更改 ParseResults?

感谢您的帮助。

顺便说一句——这段代码在解析日期、金额等方面有意义吗?

【问题讨论】:

    标签: python parsing pyparsing


    【解决方案1】:

    这种对表格数据的解析是 pyparsing 的原始案例之一。恭喜您在解析非平凡的输入文本方面取得了进展!

    与其尝试进行任何不自然的分组或其他任何不将解析的数据扭曲或组合成您想要的数据结构的事情,我只是在您获得解析结果并建立一个新的摘要结构时对其进行分析,我将其会打电话给summary。我们实际上是将数据累积到这个字典中,强烈建议在找到新键时使用默认字典来简化摘要的初始化。

    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)))
    

    完成!看看我们积累了什么key:

    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')}
    

    【讨论】:

    • 感谢您的提示@paul-mcguire。那很快!这就是我的想法 - 只需获取解析结果并用它做你需要的事情。
    猜你喜欢
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    • 2011-08-03
    • 2023-01-31
    • 2018-11-22
    • 2011-10-14
    • 2016-09-25
    • 2015-09-08
    相关资源
    最近更新 更多