150 votes

Créer une belle sortie de colonne en python

J'essaie de créer une belle liste de colonnes en python pour l'utiliser avec les outils d'administration en ligne de commande que je crée.

En gros, je veux une liste comme :

[['a', 'b', 'c'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c']]

Pour se transformer :

a            b            c
aaaaaaaaaa   b            c
a            bbbbbbbbbb   c

L'utilisation de simples tabulations ne fera pas l'affaire ici, car je ne connais pas la longueur maximale des données de chaque ligne.

C'est le même comportement que 'column -t' sous Linux

$ echo -e "a b c\naaaaaaaaaa b c\na bbbbbbbbbb c"
a b c
aaaaaaaaaa b c
a bbbbbbbbbb c

$ echo -e "a b c\naaaaaaaaaa b c\na bbbbbbbbbb c" | column -t
a           b           c
aaaaaaaaaa  b           c
a           bbbbbbbbbb  c

J'ai cherché diverses bibliothèques python pour faire cela, mais je n'ai rien trouvé d'utile.

3voto

Vilq Points 126

Pour les paresseux

qui utilisent Python 3.* y Pandas/Géopandas ; approche universelle simple en classe (pour un script 'normal', il suffit d'enlever self ) :

Fonction colorier :

    def colorize(self,s,color):
        s = color+str(s)+"\033[0m"
        return s

En-tête :

print('{0:<23} {1:>24} {2:>26} {3:>26} {4:>11} {5:>11}'.format('Road name','Classification','Function','Form of road','Length','Distance') )

et ensuite les données du cadre de données de Pandas/Geopandas :

            for index, row in clipped.iterrows():
                rdName      = self.colorize(row['name1'],"\033[32m")
                rdClass     = self.colorize(row['roadClassification'],"\033[93m")
                rdFunction  = self.colorize(row['roadFunction'],"\033[33m")
                rdForm      = self.colorize(row['formOfWay'],"\033[94m")
                rdLength    = self.colorize(row['length'],"\033[97m")
                rdDistance  = self.colorize(row['distance'],"\033[96m")
                print('{0:<30} {1:>35} {2:>35} {3:>35} {4:>20} {5:>20}'.format(rdName,rdClass,rdFunction,rdForm,rdLength,rdDistance) )

Signification de {0:<30} {1:>35} {2:>35} {3:>35} {4:>20} {5:>20} :

0, 1, 2, 3, 4, 5 -> colonnes, il y en a 6 au total dans ce cas-ci

30, 35, 20 -> largeur de la colonne (notez que vous devrez ajouter la longueur de la colonne à la longueur de la colonne). \033[96m - pour Python, il s'agit également d'une chaîne de caractères), expérimentez simplement :)

>, < -> justifier : droite, gauche (il y a = pour le remplissage avec des zéros également)

Si vous voulez distinguer par exemple la valeur maximale, vous devrez passer à une fonction spéciale de style Pandas, mais supposez que c'est suffisant pour présenter les données sur la fenêtre du terminal.

Résultat :

enter image description here

2voto

aluchko Points 11

Une légère variation sur une réponse précédente (je n'ai pas assez de rep pour la commenter). La bibliothèque de formats vous permet de spécifier la largeur et l'alignement d'un élément mais pas son point de départ, c'est-à-dire que vous pouvez dire "avoir une largeur de 20 colonnes" mais pas "commencer à la colonne 20". Ce qui nous amène à ce problème :

table_data = [
    ['a', 'b', 'c'],
    ['aaaaaaaaaa', 'b', 'c'], 
    ['a', 'bbbbbbbbbb', 'c']
]

print("first row: {: >20} {: >20} {: >20}".format(*table_data[0]))
print("second row: {: >20} {: >20} {: >20}".format(*table_data[1]))
print("third row: {: >20} {: >20} {: >20}".format(*table_data[2]))

Sortie

first row:                    a                    b                    c
second row:           aaaaaaaaaa                    b                    c
third row:                    a           bbbbbbbbbb                    c

La solution consiste bien sûr à formater également les chaînes littérales, ce qui se combine un peu bizarrement avec le format :

table_data = [
    ['a', 'b', 'c'],
    ['aaaaaaaaaa', 'b', 'c'], 
    ['a', 'bbbbbbbbbb', 'c']
]

print(f"{'first row:': <20} {table_data[0][0]: >20} {table_data[0][1]: >20} {table_data[0][2]: >20}")
print("{: <20} {: >20} {: >20} {: >20}".format(*['second row:', *table_data[1]]))
print("{: <20} {: >20} {: >20} {: >20}".format(*['third row:', *table_data[1]]))

Sortie

first row:                              a                    b                    c
second row:                    aaaaaaaaaa                    b                    c
third row:                     aaaaaaaaaa                    b                    c

1voto

user1529756 Points 11

Cela définit des largeurs de colonne indépendantes et adaptées, basées sur le paramètre max utilisé dans d'autres réponses.

data = [['a', 'b', 'c'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c']]
padding = 2
col_widths = [max(len(w) for w in [r[cn] for r in data]) + padding for cn in range(len(data[0]))]
format_string = "{{:{}}}{{:{}}}{{:{}}}".format(*col_widths)
for row in data:
    print(format_string.format(*row))

0voto

Leonard Points 317

J'ai trouvé cette réponse super utile et élégante, provenant de aquí :

matrix = [["A", "B"], ["C", "D"]]

print('\n'.join(['\t'.join([str(cell) for cell in row]) for row in matrix]))

Sortie

A   B
C   D

0voto

marko.ristin Points 28

Voici une variante de la réponse de Shawn Chin. La largeur est fixée par colonne, et non sur l'ensemble des colonnes. Il y a également une bordure sous la première ligne et entre les colonnes. ( icontrat est utilisée pour faire respecter les contrats).

@icontract.pre(
    lambda table: not table or all(len(row) == len(table[0]) for row in table))
@icontract.post(lambda table, result: result == "" if not table else True)
@icontract.post(lambda result: not result.endswith("\n"))
def format_table(table: List[List[str]]) -> str:
    """
    Format the table as equal-spaced columns.

    :param table: rows of cells
    :return: table as string
    """
    cols = len(table[0])

    col_widths = [max(len(row[i]) for row in table) for i in range(cols)]

    lines = []  # type: List[str]
    for i, row in enumerate(table):
        parts = []  # type: List[str]

        for cell, width in zip(row, col_widths):
            parts.append(cell.ljust(width))

        line = " | ".join(parts)
        lines.append(line)

        if i == 0:
            border = []  # type: List[str]

            for width in col_widths:
                border.append("-" * width)

            lines.append("-+-".join(border))

    result = "\n".join(lines)

    return result

Voici un exemple :

>>> table = [['column 0', 'another column 1'], ['00', '01'], ['10', '11']]
>>> result = packagery._format_table(table=table)
>>> print(result)
column 0 | another column 1
---------+-----------------
00       | 01              
10       | 11

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