Maison  >  Article  >  développement back-end  >  Comment puis-je analyser efficacement les lignes de fichiers de largeur fixe en Python ?

Comment puis-je analyser efficacement les lignes de fichiers de largeur fixe en Python ?

Barbara Streisand
Barbara Streisandoriginal
2024-10-30 17:09:26374parcourir

How can I efficiently parse fixed-width file lines in Python?

Analyse rapide des lignes de fichiers à largeur fixe

L'analyse des fichiers à largeur fixe, où chaque colonne occupe un nombre spécifique de caractères dans une ligne, peut être une tâche nécessitant de l'efficacité. Voici une discussion sur la façon d'y parvenir efficacement :

Le problème

Considérons un fichier à largeur fixe où les 20 premiers caractères représentent une colonne, suivis de 21 à 30 pour la seconde, et ainsi sur. Étant donné une ligne de 100 caractères, comment pouvons-nous l'analyser efficacement dans ses colonnes respectives ?

Solutions

1. Module Struct :

L'utilisation du module struct de la bibliothèque standard Python offre à la fois simplicité et rapidité grâce à son implémentation en C. Le code ci-dessous démontre son utilisation :

<code class="python">import struct

fieldwidths = (2, -10, 24)
fmtstring = ' '.join('{}{}'.format(abs(fw), 'x' if fw < 0 else 's') for fw in fieldwidths)

# Convert Unicode input to bytes and decode result.
unpack = struct.Struct(fmtstring).unpack_from  # Alias.
parse = lambda line: tuple(s.decode() for s in unpack(line.encode()))

# Parse a sample line.
line = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n'
fields = parse(line)
print('fields:', fields)</code>

Sortie :

fmtstring: '2s 10x 24s', record size: 36 chars
fields: ('AB', 'MNOPQRSTUVWXYZ0123456789')

2. Découpage de chaîne optimisé :

Bien que le découpage de chaîne soit couramment utilisé, il peut devenir fastidieux pour les grandes lignes. Voici une approche optimisée :

<code class="python">from itertools import zip_longest
from itertools import accumulate

def make_parser(fieldwidths):
    # Calculate slice boundaries.
    cuts = tuple(cut for cut in accumulate(abs(fw) for fw in fieldwidths))
    # Create field slice tuples.
    flds = tuple(zip_longest(cuts, (0,)+cuts))[:-1]  # Ignore final value.
    # Construct the parsing function.
    parse = lambda line: tuple(line[i:j] for i, j in flds)
    parse.size = sum(abs(fw) for fw in fieldwidths)
    parse.fmtstring = ' '.join('{}{}'.format(abs(fw), 'x' if fw < 0 else 's')
                                            for fw in fieldwidths)
    return parse

# Parse a sample line.
line = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\n'
fieldwidths = (2, -10, 24)  # Negative values indicate ignored padding fields.
parse = make_parser(fieldwidths)
fields = parse(line)
print('fmtstring:', parse.fmtstring, ', record size:', parse.size, 'chars')
print('fields:', fields)</code>

Sortie :

fmtstring: '2s 10x 24s', record size: 36 chars
fields: ('AB', 'MNOPQRSTUVWXYZ0123456789')

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn