2 votes

Joindre les résultats de l'analyse syntaxique

J'ai récemment commencé à utiliser pyparsing et je suis coincé avec ce qui suit : Il y a des données organisées en colonnes dont le nombre n'est pas connu et, en outre, cette section peut apparaître plusieurs fois dans l'entrée. Voir le code ci-dessous pour un exemple.

# -*- 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

Actuellement, par exemple, p.it ressemble à [[1, 2, 3], [4, 5]] Ce dont j'ai besoin, c'est [1,2,3,4,5] également pour d'autres parties, de sorte qu'au lieu de p.details[0]['18.04.2013'].data[2] Je pourrais le faire p.details['18.04.2013'].data[2] ensuite.

Je suis à court d'idées - est-il possible de joindre les résultats d'une manière simple ou dois-je modifier ParseResults avec une autre fonction ?

Merci de votre aide.

BTW - ce code a-t-il un sens en ce qui concerne l'analyse des dates, des montants, etc.

1voto

Paul McGuire Points 24790

Ce type d'analyse de données tabulaires est l'un des cas originaux pour lesquels pyparsing a été écrit. Félicitations pour avoir réussi à analyser un texte d'entrée non trivial !

Plutôt que d'essayer de faire des regroupements non naturels ou autres pour tordre ou combiner les données analysées dans la structure de données souhaitée, je me contenterais de parcourir les résultats analysés tels que vous les avez obtenus et de construire une nouvelle structure de résumé, que j'appellerai summary . Nous allons en fait accumuler des données dans ce dict, ce qui suggère fortement d'utiliser un dict par défaut pour simplifier l'initialisation du résumé lorsqu'une nouvelle clé est trouvée.

from collections import defaultdict
summary = defaultdict(dict)

En examinant la structure actuelle renvoyée en p vous obtenez des en-têtes d'articles et des ensembles de données détaillées rassemblés dans les résultats nommés. it y details . Nous pouvons les regrouper pour obtenir les en-têtes et les données de chaque section. Ensuite, pour chaque ligne dans les détails, nous ferons une dictée des valeurs détaillées en zippant les en-têtes des éléments avec les valeurs des données analysées. Ensuite, nous mettrons à jour la valeur du résumé, dont la clé est l'élément 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)))

C'est fait ! Voyez quelles sont les clés que nous avons accumulées :

print summary.keys()

donne :

['20.04.2013', '18.04.2013', '17.04.2013', '19.04.2013']

Imprimer les données accumulées pour le "18.04.2013" :

print summary['18.04.2013']

donne :

{1: Decimal('548481.10'), 2: Decimal('46383.00'), 3: Decimal('29810.00'), 4: Decimal('548481.10'), 5: Decimal('56383.00')}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X