Я пытаюсь сформулировать функцию, которая берет список списков строк и отображает его в хорошо организованной таблице с выравниванием каждого столбца по правому краю. Предположим, что все внутренние списки будут содержать одинаковое количество строк. Например, значение может выглядеть так:

tableData = [['apples', 'oranges', 'cherries', 'banana'],

['Alice', 'Bob', 'Carol', 'David'],

['dogs', 'cats', 'moose', 'goose']]

Ваша функция выведет следующее (выровнено справа):

    apples Alice   dogs

   oranges   Bob   cats

  cherries Carol  moose

    banana David  goose

Используя данный намек, я пришел к:

def printable(tableData):
    newTable = np.zeros((len(tableData[0]),len(tableData)))
    colWidths = [0] * len(tableData)
    for i in range(0,len(tableData)):
        colWidths[i] = max(tableData[i], key=len)
    largest = max(colWidths, key=len)
    for i in range(0,len(tableData)):
        for j in range(0,len(tableData[0])):
            newTable[i][j] = tableData[j][i].rjust(len(largest))

Я потрясен, нет. из для петель. Как новичок, я все еще выхожу из режима «для цикла». Кроме того, я размышляю над лучшей формой атаки для этой проблемы. Благодарю.

4
srkdb 20 Авг 2018 в 22:09

4 ответа

Лучший ответ

Вот один из способов сделать это на простом Python. Мы используем zip для транспонирования таблицы, чтобы мы могли получить максимальную ширину каждого столбца.

table_data = [
    ['apples', 'oranges', 'cherries', 'banana'],
    ['Alice', 'Bob', 'Carol', 'David'],
    ['dogs', 'cats', 'moose', 'goose'],
]

# Determine the width of each column
widths = [max(map(len, column)) for column in zip(*table_data)]
new_table = [[s.rjust(w) for s, w in zip(row, widths)]
    for row in table_data]

for row in new_table:
    print(row)

вывод

['apples', 'oranges', 'cherries', 'banana']
[' Alice', '    Bob', '   Carol', ' David']
['  dogs', '   cats', '   moose', ' goose']

Если вам действительно не нужен новый 2D-список, и вы просто хотите распечатать данные, вы можете сделать что-то вроде этого:

for row in table_data:
    print(*(s.rjust(w) for s, w in zip(row, widths)))

вывод

apples oranges cherries banana
 Alice     Bob    Carol  David
  dogs    cats    moose  goose

Вот новая версия, которая транспонирует таблицу.

widths = [max(map(len, row)) for row in table_data]
new_table = [[s.rjust(w) for s, w in zip(row, widths)] for row in zip(*table_data)]
for row in new_table:
    print(row)

вывод

['  apples', 'Alice', ' dogs']
[' oranges', '  Bob', ' cats']
['cherries', 'Carol', 'moose']
['  banana', 'David', 'goose']
4
PM 2Ring 20 Авг 2018 в 20:12

Я думал, что вам пришлось написать алгоритм самостоятельно, но в своей попытке вы использовали numpy, поэтому я предполагаю, что вы также можете использовать pandas.

Вы можете просто загрузить свои данные во фрейм данных, транспонировать их и использовать уже созданный класс __repr__ панд DataFrame

Другими словами,

pd.DataFrame(arr).T.__repr__()

Что дает

'          0      1      2\n0    apples  Alice   dogs\n1   oranges    Bob   cats\n2  cherries  Carol  moose\n3    banana  David  goose'

Так что, если вы print это, вы получите

          0      1      2
0    apples  Alice   dogs
1   oranges    Bob   cats
2  cherries  Carol  moose
3    banana  David  goose

Если вы не хотите печатать идентификаторы столбцов, вы можете поиграть с выводом __repr__

print('\n'.join([x[1:] for x in df.__repr__().split('\n')[1:]]))


    apples  Alice   dogs
   oranges    Bob   cats
  cherries  Carol  moose
    banana  David  goose
2
rafaelc 20 Авг 2018 в 19:22
tableData = [
    ['apples', 'oranges', 'cherries', 'banana'],
    ['Alice', 'Bob', 'Carol', 'David'],
    ['dogs', 'cats', 'moose', 'goose']
]

# Determine maximum column width
colWidth = 0
for x in tableData:
    colWidth = max(colWidth, len(max(x, key=len)))

# Use zip to "flip" your rows and columns
# Note that the * first unpacks your list of lists 

for row in zip(*tableData):
     # Join each row element together into a string, right justifying each element to your column width as you go
    print ''.join([ele.rjust(colWidth) for ele in row])
2
Bill S. 20 Авг 2018 в 19:38

С комбинацией панд to_string, index=False, transpose и splitlines

Существует опция header=None, но она портит выравнивание по неизвестной причине. Поэтому я оставляю заголовок и удаляю его splitlines[1:]

import pandas as pd
print('\n'.join(pd.DataFrame(table_data).T.to_string(index=False).splitlines()[1:]))

  apples  Alice   dogs
 oranges    Bob   cats
cherries  Carol  moose
  banana  David  goose

F-строки + str.format

Создайте функцию str.format, основанную на максимальной длине строки.
Вдохновленный PM 2Ring

f = '  '.join([f"{{:>{max(map(len, r))}}}" for r in table_data]).format
print('\n'.join([f(*t) for t in zip(*table_data)]))

  apples  Alice   dogs
 oranges    Bob   cats
cherries  Carol  moose
  banana  David  goose

Детали

Этот:

'  '.join([f"{{:>{max(map(len, r))}}}" for r in table_data])

Создает строку, которая выглядит следующим образом:

'{:>8}  {:>5}  {:>5}'

8, 5, 5 - это максимальная длина строки в строке. Я преобразовываю это в функцию форматирования, добавляя .format в конце. Теперь это функция, которая принимает 3 позиционных аргумента и форматирует строку с заданным интервалом.

3
piRSquared 20 Авг 2018 в 21:03
51937095