Quelle est la meilleure façon de convertir un tableau basé sur du texte et des espaces pour le convertir en tableau?

Je reçois en dessous de la sortie de l'un des lecteurs matériels. J'ai besoin d'analyser et d'obtenir des valeurs pour chaque cellule.

TANK  PRODUCT               GALLONS  INCHES   WATER  DEG F   ULLAGE

  1   REGULAR UNLEADED  87    56987   75.77     0.0   83.3     4785
  2   18                       4578   86.08           83.6     1661
  3   SAMPLE                   1234   77.94     0.0   86.4     2140

Deux cas de test

  • Lorsque la colonne Produit comme exemple d'espace "12 Données"
  • Lorsque la colonne Produit comme exemple de deux espaces "REGULAR UNLEADED 87"
  • Lorsqu'une cellule est vide.
-2
AjmeraInfo 20 oct. 2020 à 14:07

2 réponses

Meilleure réponse

Puisque vous avez des espaces dans les cellules et vos données, vous avez besoin d'un peu de magie RegExp:

import re

s = """
TANK  PRODUCT               GALLONS  INCHES   WATER  DEG F   ULLAGE

  1   12 Data                 56987   75.77     0.0   83.3     4785
  2   18                       4578   86.08     0.0   83.6     1661
  3   SAMPLE                   1234   77.94     0.0   86.4     2140
"""

s = re.sub('^\n', '', s)     # remove empty line a the start of 's'
s = re.sub('\n+ +', '\n', s) # remove spaces at the start of lines and empty lines
s = re.sub('\s +', '\t', s)  # replace two or more spaces with tab

table = [row.split('\t') for row in s.splitlines()]

print(table)

Production:

[
    ['TANK', 'PRODUCT', 'GALLONS', 'INCHES', 'WATER', 'DEG F', 'ULLAGE'], 
    ['1', '12 Data', '56987', '75.77', '0.0', '83.3', '4785'], 
    ['2', '18', '4578', '86.08', '0.0', '83.6', '1661'], 
    ['3', 'SAMPLE', '1234', '77.94', '0.0', '86.4', '2140']
]

Mais cela ne fonctionne que si vous avez au moins 2 espaces à l'extérieur des cellules et utilisez des espaces simples à l'intérieur des cellules.


Variante courte (la même sortie):

import re

s = """
TANK  PRODUCT               GALLONS  INCHES   WATER  DEG F   ULLAGE

  1   12 Data                 56987   75.77     0.0   83.3     4785
  2   18                       4578   86.08     0.0   83.6     1661
  3   SAMPLE                   1234   77.94     0.0   86.4     2140
"""

s = re.sub('  +', '\t', s)   # replace two or more spaces with tab

table = [row.strip().split('\t') for row in s.splitlines() if len(row) > 1]

print(table)

Version étendue. Il peut gérer les cellules vides:

import re
from pprint import pprint

s = """
TANK  PRODUCT               GALLONS  INCHES   WATER  DEG F   ULLAGE

  1   REGULAR UNLEADED 87     56987   75.77     0.0   83.3     4785
  2   18                       4578   86.08           83.6     1661
  3   SAMPLE                   1234   77.94     0.0   86.4     2140
"""

lines = s.splitlines()                  # split the data by lines
lines = [l for l in lines if len(l)>0]  # remove empty lines

# function takes a line
# and returns a list of separators (positions of left edges of the cells)
def get_separators(line):
    separators = []
    i = 0
    while i < len(line)-1:
        i += 1
        if line[i] == " ": continue      # skip all spaces
        while i < len(line)-2:
            i += 1
            if line[i] != " ": continue  # then skip all non spaces
            if line[i+1] == " ":         # if there are two spaces
                separators.append(i)     # add the position to the separators
                break
    separators.append(len(line))         # add a separator at the end
    return separators

# get separators from the first line
separators = get_separators(lines[0])

# go through all lines and adjust positions of separators
for line in lines:
    separators_cur_line = get_separators(line)
    if len(separators) != len(separators_cur_line): continue
    for i, sep in enumerate(separators_cur_line):
        if sep > separators[i]:
            separators[i] = sep

# function takes a line and a list of separators
# and returns a list of cells (the line divided by the separators)
def get_cells(line, separators):
    res=[]
    start = 0
    for end in separators:
        cell = line[start:end].strip()
        start = end
        res.append(cell)
    return res

# get cells from all lines
data = [get_cells(line, separators) for line in lines]

pprint(data)

Production:

[
   ['TANK', 'PRODUCT', 'GALLONS', 'INCHES', 'WATER', 'DEG F', 'ULLAGE'],
   ['1', 'REGULAR UNLEADED 87', '56987', '75.77', '0.0', '83.3', '4785'],
   ['2', '18', '4578', '86.08', '', '83.6', '1661'],
   ['3', 'SAMPLE', '1234', '77.94', '0.0', '86.4', '2140']
]

Limites:

  • Seuls les espaces simples autorisés à l'intérieur des cellules.
  • Au moins deux espaces doivent être entre les colonnes et les cellules.
  • La cellule ne peut contenir qu'une seule ligne.
1
Yuri Khristich 22 oct. 2020 à 00:32

Essayez d'utiliser les méthodes str.splitlines() et str.split(), par exemple:

s = """
TANK  PRODUCT               GALLONS  INCHES   WATER  DEG F   ULLAGE

  1   12                      56987   75.77     0.0   83.3     4785
  2   18                       4578   86.08     0.0   83.6     1661
  3   SAMPLE                   1234   77.94     0.0   86.4     2140
"""
result = []
for row in s.splitlines():
    result.append(row.split())

Alternativement, en utilisant la compréhension de liste:

result = [row.split() for row in s.splitlines()]
2
Szymon 20 oct. 2020 à 11:17