python에서 nice 열 출력을 만듭니다.
제가 작성한 명령줄 관리 도구에 사용할 파이썬으로 멋진 컬럼 목록을 작성하려고 합니다.
기본적으로 다음과 같은 목록을 원합니다.
[['a', 'b', 'c'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c']]
변경 내용:
a b c
aaaaaaaaaa b c
a bbbbbbbbbb c
각 행의 가장 긴 데이터를 모르기 때문에 일반 탭을 사용하면 문제가 해결되지 않습니다.
이것은 Linux의 'column - t'와 같은 동작입니다.
$ 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
다양한 파이썬 라이브러리를 찾아봤지만 유용한 것을 찾을 수 없었습니다.
Python 2.6+ 이후부터는 다음과 같은 방법으로 형식 문자열을 사용하여 열을 최소 20자로 설정하고 텍스트를 오른쪽으로 정렬할 수 있습니다.
table_data = [
['a', 'b', 'c'],
['aaaaaaaaaa', 'b', 'c'],
['a', 'bbbbbbbbbb', 'c']
]
for row in table_data:
print("{: >20} {: >20} {: >20}".format(*row))
출력:
a b c
aaaaaaaaaa b c
a bbbbbbbbbb c
data = [['a', 'b', 'c'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c']]
col_width = max(len(word) for row in data for word in row) + 2 # padding
for row in data:
print "".join(word.ljust(col_width) for word in row)
a b c
aaaaaaaaaa b c
a bbbbbbbbbb c
가장 긴너비를 후 를 사용합니다..ljust()
각 열을 인쇄할 때 필요한 패딩을 추가합니다.
같은 @와 @은 @lvc @Preet @Preet, @preet의 과 좀 더이 된 것.column -t
을 사용법
>>> rows = [ ['a', 'b', 'c', 'd']
... , ['aaaaaaaaaa', 'b', 'c', 'd']
... , ['a', 'bbbbbbbbbb', 'c', 'd']
... ]
...
>>> widths = [max(map(len, col)) for col in zip(*rows)]
>>> for row in rows:
... print " ".join((val.ljust(width) for val, width in zip(row, widths)))
...
a b c d
aaaaaaaaaa b c d
a bbbbbbbbbb c d
파티에는 조금 늦었고, 제가 쓴 패키지에 대한 뻔뻔한 플러그도 있지만, Columnar 패키지도 확인하실 수 있습니다.
입력 목록과 헤더 목록을 가져와 테이블 형식의 문자열을 출력합니다.이 스니펫에서는 도커 에스크테이블을 만듭니다.
from columnar import columnar
headers = ['name', 'id', 'host', 'notes']
data = [
['busybox', 'c3c37d5d-38d2-409f-8d02-600fd9d51239', 'linuxnode-1-292735', 'Test server.'],
['alpine-python', '6bb77855-0fda-45a9-b553-e19e1a795f1e', 'linuxnode-2-249253', 'The one that runs python.'],
['redis', 'afb648ba-ac97-4fb2-8953-9a5b5f39663e', 'linuxnode-3-3416918', 'For queues and stuff.'],
['app-server', 'b866cd0f-bf80-40c7-84e3-c40891ec68f9', 'linuxnode-4-295918', 'A popular destination.'],
['nginx', '76fea0f0-aa53-4911-b7e4-fae28c2e469b', 'linuxnode-5-292735', 'Traffic Cop'],
]
table = columnar(data, headers, no_borders=True)
print(table)
아니면 색상과 테두리가 있는 작은 팬시어를 얻을 수도 있습니다.
열 크기 조정 알고리즘에 대한 자세한 내용과 API의 나머지 내용을 보려면 위의 링크를 확인하거나 Columnar GitHub Repo를 참조하십시오.
와, 17개밖에 안 맞혔어.비단뱀의 선( ")은 "명백한 방법은 하나, 그리고 가급적 하나뿐이어야 한다"고 말한다.
18번째 방법은 다음과 같습니다.테이블레이트 패키지는 테이블로 표시할 수 있는 다수의 데이터 유형을 지원합니다.다음은 해당 문서에서 개정한 간단한 예입니다.
from tabulate import tabulate
table = [["Sun",696000,1989100000],
["Earth",6371,5973.6],
["Moon",1737,73.5],
["Mars",3390,641.85]]
print(tabulate(table, headers=["Planet","R (km)", "mass (x 10^29 kg)"]))
출력되는 것
Planet R (km) mass (x 10^29 kg)
-------- -------- -------------------
Sun 696000 1.9891e+09
Earth 6371 5973.6
Moon 1737 73.5
Mars 3390 641.85
2개의 패스로 이 작업을 수행해야 합니다.
- 각 열의 최대 너비를 가져옵니다.
- 첫 에 관한 의 형식을 합니다.
str.ljust()
★★★★★★★★★★★★★★★★★」str.rjust()
이와 같이 열을 옮기는 것은 zip을 위한 작업입니다.
>>> a = [['a', 'b', 'c'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c']]
>>> list(zip(*a))
[('a', 'aaaaaaaaaa', 'a'), ('b', 'b', 'bbbbbbbbbb'), ('c', 'c', 'c')]
을 합니다.max
:
>>> trans_a = zip(*a)
>>> [max(len(c) for c in b) for b in trans_a]
[10, 10, 1]
패딩과 입니다.print
:
>>> col_lenghts = [max(len(c) for c in b) for b in trans_a]
>>> padding = ' ' # You might want more
>>> padding.join(s.ljust(l) for s,l in zip(a[0], col_lenghts))
'a b c'
다음과 같은 고급 테이블을 얻으려면
---------------------------------------------------
| First Name | Last Name | Age | Position |
---------------------------------------------------
| John | Smith | 24 | Software |
| | | | Engineer |
---------------------------------------------------
| Mary | Brohowski | 23 | Sales |
| | | | Manager |
---------------------------------------------------
| Aristidis | Papageorgopoulos | 28 | Senior |
| | | | Reseacher |
---------------------------------------------------
다음 Python 레시피를 사용할 수 있습니다.
'''
From http://code.activestate.com/recipes/267662-table-indentation/
PSF License
'''
import cStringIO,operator
def indent(rows, hasHeader=False, headerChar='-', delim=' | ', justify='left',
separateRows=False, prefix='', postfix='', wrapfunc=lambda x:x):
"""Indents a table by column.
- rows: A sequence of sequences of items, one sequence per row.
- hasHeader: True if the first row consists of the columns' names.
- headerChar: Character to be used for the row separator line
(if hasHeader==True or separateRows==True).
- delim: The column delimiter.
- justify: Determines how are data justified in their column.
Valid values are 'left','right' and 'center'.
- separateRows: True if rows are to be separated by a line
of 'headerChar's.
- prefix: A string prepended to each printed row.
- postfix: A string appended to each printed row.
- wrapfunc: A function f(text) for wrapping text; each element in
the table is first wrapped by this function."""
# closure for breaking logical rows to physical, using wrapfunc
def rowWrapper(row):
newRows = [wrapfunc(item).split('\n') for item in row]
return [[substr or '' for substr in item] for item in map(None,*newRows)]
# break each logical row into one or more physical ones
logicalRows = [rowWrapper(row) for row in rows]
# columns of physical rows
columns = map(None,*reduce(operator.add,logicalRows))
# get the maximum of each column by the string length of its items
maxWidths = [max([len(str(item)) for item in column]) for column in columns]
rowSeparator = headerChar * (len(prefix) + len(postfix) + sum(maxWidths) + \
len(delim)*(len(maxWidths)-1))
# select the appropriate justify method
justify = {'center':str.center, 'right':str.rjust, 'left':str.ljust}[justify.lower()]
output=cStringIO.StringIO()
if separateRows: print >> output, rowSeparator
for physicalRows in logicalRows:
for row in physicalRows:
print >> output, \
prefix \
+ delim.join([justify(str(item),width) for (item,width) in zip(row,maxWidths)]) \
+ postfix
if separateRows or hasHeader: print >> output, rowSeparator; hasHeader=False
return output.getvalue()
# written by Mike Brown
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061
def wrap_onspace(text, width):
"""
A word-wrap function that preserves existing line breaks
and most spaces in the text. Expects that existing line
breaks are posix newlines (\n).
"""
return reduce(lambda line, word, width=width: '%s%s%s' %
(line,
' \n'[(len(line[line.rfind('\n')+1:])
+ len(word.split('\n',1)[0]
) >= width)],
word),
text.split(' ')
)
import re
def wrap_onspace_strict(text, width):
"""Similar to wrap_onspace, but enforces the width constraint:
words longer than width are split."""
wordRegex = re.compile(r'\S{'+str(width)+r',}')
return wrap_onspace(wordRegex.sub(lambda m: wrap_always(m.group(),width),text),width)
import math
def wrap_always(text, width):
"""A simple word-wrap function that wraps text on exactly width characters.
It doesn't split the text in words."""
return '\n'.join([ text[width*i:width*(i+1)] \
for i in xrange(int(math.ceil(1.*len(text)/width))) ])
if __name__ == '__main__':
labels = ('First Name', 'Last Name', 'Age', 'Position')
data = \
'''John,Smith,24,Software Engineer
Mary,Brohowski,23,Sales Manager
Aristidis,Papageorgopoulos,28,Senior Reseacher'''
rows = [row.strip().split(',') for row in data.splitlines()]
print 'Without wrapping function\n'
print indent([labels]+rows, hasHeader=True)
# test indent with different wrapping functions
width = 10
for wrapper in (wrap_always,wrap_onspace,wrap_onspace_strict):
print 'Wrapping function: %s(x,width=%d)\n' % (wrapper.__name__,width)
print indent([labels]+rows, hasHeader=True, separateRows=True,
prefix='| ', postfix=' |',
wrapfunc=lambda x: wrapper(x,width))
# output:
#
#Without wrapping function
#
#First Name | Last Name | Age | Position
#-------------------------------------------------------
#John | Smith | 24 | Software Engineer
#Mary | Brohowski | 23 | Sales Manager
#Aristidis | Papageorgopoulos | 28 | Senior Reseacher
#
#Wrapping function: wrap_always(x,width=10)
#
#----------------------------------------------
#| First Name | Last Name | Age | Position |
#----------------------------------------------
#| John | Smith | 24 | Software E |
#| | | | ngineer |
#----------------------------------------------
#| Mary | Brohowski | 23 | Sales Mana |
#| | | | ger |
#----------------------------------------------
#| Aristidis | Papageorgo | 28 | Senior Res |
#| | poulos | | eacher |
#----------------------------------------------
#
#Wrapping function: wrap_onspace(x,width=10)
#
#---------------------------------------------------
#| First Name | Last Name | Age | Position |
#---------------------------------------------------
#| John | Smith | 24 | Software |
#| | | | Engineer |
#---------------------------------------------------
#| Mary | Brohowski | 23 | Sales |
#| | | | Manager |
#---------------------------------------------------
#| Aristidis | Papageorgopoulos | 28 | Senior |
#| | | | Reseacher |
#---------------------------------------------------
#
#Wrapping function: wrap_onspace_strict(x,width=10)
#
#---------------------------------------------
#| First Name | Last Name | Age | Position |
#---------------------------------------------
#| John | Smith | 24 | Software |
#| | | | Engineer |
#---------------------------------------------
#| Mary | Brohowski | 23 | Sales |
#| | | | Manager |
#---------------------------------------------
#| Aristidis | Papageorgo | 28 | Senior |
#| | poulos | | Reseacher |
#---------------------------------------------
Python 레시피 페이지에는 몇 가지 개선 사항이 포함되어 있습니다.
pandas
데이터 프레임 생성 기반 솔루션:
import pandas as pd
l = [['a', 'b', 'c'], ['aaaaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'c']]
df = pd.DataFrame(l)
print(df)
0 1 2
0 a b c
1 aaaaaaaaaa b c
2 a bbbbbbbbbb c
인덱스와 헤더 값을 삭제하고 원하는 출력을 작성하려면 다음 방법을 사용할 수 있습니다.
result = df.to_string(index=False, header=False)
print(result)
a b c
aaaaaaaaaa b c
a bbbbbbbbbb c
Scolp는 컬럼 너비를 자동 조정하면서 스트리밍 컬럼 데이터를 쉽게 인쇄할 수 있는 새로운 라이브러리입니다.
(면책자:제가 작가입니다.)
게으른 사람용
Python 3.* 및 Panda/Geopandas를 사용하는 경우, 범용적인 심플한 클래스 내 접근 방식('일반' 스크립트의 경우 자체 제거):
기능 컬러화:
def colorize(self,s,color):
s = color+str(s)+"\033[0m"
return s
머리글:
print('{0:<23} {1:>24} {2:>26} {3:>26} {4:>11} {5:>11}'.format('Road name','Classification','Function','Form of road','Length','Distance') )
다음으로 Panda/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) )
「 」의 {0:<30} {1:>35} {2:>35} {3:>35} {4:>20} {5:>20}
:
0, 1, 2, 3, 4, 5
이총입니다. -> 아, 아, 6개입니다.
30, 35, 20
(해야 합니다) -> > > > > > > > > > > > > > > > > > > 의 길이를 추가해야 합니다\033[96m
입니다.) - - Python의 경우입니다.
>, <
: : -> 있습니다), 왼쪽(있음)=
0으로 채우다)
예를 들어 최대값을 구별하려면 Panda 스타일의 특수 기능으로 전환해야 하지만 터미널 창에 데이터를 표시하기에 충분하다고 가정합니다.
결과:
이전 답변에 대한 약간의 변화(코멘트를 할 수 있는 충분한 담당자가 없습니다).형식 라이브러리를 사용하면 요소의 너비와 정렬을 지정할 수 있지만 요소의 시작 위치는 지정할 수 없습니다. 즉, "20열 너비"는 지정할 수 있지만 "20열에서 시작"은 지정할 수 없습니다.이로 인해 다음과 같은 문제가 발생합니다.
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]))
산출량
first row: a b c
second row: aaaaaaaaaa b c
third row: a bbbbbbbbbb c
물론 리터럴 문자열도 포맷합니다.이 문자열은 포맷과 약간 이상하게 조합됩니다.
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]]))
산출량
first row: a b c
second row: aaaaaaaaaa b c
third row: aaaaaaaaaa b c
그러면 다른 응답에 사용된 최대 메트릭을 기준으로 독립적이고 가장 적합한 열 너비가 설정됩니다.
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))
테이블로 포맷하려면 오른쪽 패딩이 필요합니다.중입니다.Python 패키지는 Python은 Python 패키지입니다.prettytable
라이브러리에 의존하지 않는 것이 좋지만, 이 패키지는 모든 엣지 케이스를 처리해, 더 이상 의존하지 않고 심플합니다.
x = PrettyTable()
x.field_names =["field1", "field2", "field3"]
x.add_row(["col1_content", "col2_content", "col3_content"])
print(x)
다른 답변을 바탕으로 상당히 읽기 쉽고 견고한 솔루션을 구축했습니다.
data = [['a', 'b', 'c'], ['aaaaaaaa', 'b', 'c'], ['a', 'bbbbbbbbbb', 'ccc']]
padding = 4
# build a format string of max widths
# ex: '{:43}{:77}{:104}'
num_cols = len(data[0])
widths = [0] * num_cols
for row in data:
for i, value in enumerate(row):
widths[i] = max(widths[i], len(str(value)))
format_string = "".join([f'{{:{w+padding}}}' for w in widths])
# print the data
for row in data:
print(format_string.format(*[str(x) for x in row]))
'보다 낫다'를 뒷받침합니다.NoneType
기록상, 몇 가지 사항을 에 싸서str()
여기 Shawn Chin의 답변의 변형이 있다.너비는 모든 열이 아니라 열별로 고정됩니다.첫 번째 행 아래 및 열 사이에는 테두리도 있습니다.(계약 적용에는 icontract 라이브러리가 사용됩니다.)
@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
다음은 예를 제시하겠습니다.
>>> 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
Python 3 및 PEP8 준거로 @Franck Dernoncourt 고급 레시피 업데이트
import io
import math
import operator
import re
import functools
from itertools import zip_longest
def indent(
rows,
has_header=False,
header_char="-",
delim=" | ",
justify="left",
separate_rows=False,
prefix="",
postfix="",
wrapfunc=lambda x: x,
):
"""Indents a table by column.
- rows: A sequence of sequences of items, one sequence per row.
- hasHeader: True if the first row consists of the columns' names.
- headerChar: Character to be used for the row separator line
(if hasHeader==True or separateRows==True).
- delim: The column delimiter.
- justify: Determines how are data justified in their column.
Valid values are 'left','right' and 'center'.
- separateRows: True if rows are to be separated by a line
of 'headerChar's.
- prefix: A string prepended to each printed row.
- postfix: A string appended to each printed row.
- wrapfunc: A function f(text) for wrapping text; each element in
the table is first wrapped by this function."""
# closure for breaking logical rows to physical, using wrapfunc
def row_wrapper(row):
new_rows = [wrapfunc(item).split("\n") for item in row]
return [[substr or "" for substr in item] for item in zip_longest(*new_rows)]
# break each logical row into one or more physical ones
logical_rows = [row_wrapper(row) for row in rows]
# columns of physical rows
columns = zip_longest(*functools.reduce(operator.add, logical_rows))
# get the maximum of each column by the string length of its items
max_widths = [max([len(str(item)) for item in column]) for column in columns]
row_separator = header_char * (
len(prefix) + len(postfix) + sum(max_widths) + len(delim) * (len(max_widths) - 1)
)
# select the appropriate justify method
justify = {"center": str.center, "right": str.rjust, "left": str.ljust}[
justify.lower()
]
output = io.StringIO()
if separate_rows:
print(output, row_separator)
for physicalRows in logical_rows:
for row in physicalRows:
print( output, prefix + delim.join(
[justify(str(item), width) for (item, width) in zip(row, max_widths)]
) + postfix)
if separate_rows or has_header:
print(output, row_separator)
has_header = False
return output.getvalue()
# written by Mike Brown
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061
def wrap_onspace(text, width):
"""
A word-wrap function that preserves existing line breaks
and most spaces in the text. Expects that existing line
breaks are posix newlines (\n).
"""
return functools.reduce(
lambda line, word, i_width=width: "%s%s%s"
% (
line,
" \n"[
(
len(line[line.rfind("\n") + 1 :]) + len(word.split("\n", 1)[0])
>= i_width
)
],
word,
),
text.split(" "),
)
def wrap_onspace_strict(text, i_width):
"""Similar to wrap_onspace, but enforces the width constraint:
words longer than width are split."""
word_regex = re.compile(r"\S{" + str(i_width) + r",}")
return wrap_onspace(
word_regex.sub(lambda m: wrap_always(m.group(), i_width), text), i_width
)
def wrap_always(text, width):
"""A simple word-wrap function that wraps text on exactly width characters.
It doesn't split the text in words."""
return "\n".join(
[
text[width * i : width * (i + 1)]
for i in range(int(math.ceil(1.0 * len(text) / width)))
]
)
if __name__ == "__main__":
labels = ("First Name", "Last Name", "Age", "Position")
data = """John,Smith,24,Software Engineer
Mary,Brohowski,23,Sales Manager
Aristidis,Papageorgopoulos,28,Senior Reseacher"""
rows = [row.strip().split(",") for row in data.splitlines()]
print("Without wrapping function\n")
print(indent([labels] + rows, has_header=True))
# test indent with different wrapping functions
width = 10
for wrapper in (wrap_always, wrap_onspace, wrap_onspace_strict):
print("Wrapping function: %s(x,width=%d)\n" % (wrapper.__name__, width))
print(
indent(
[labels] + rows,
has_header=True,
separate_rows=True,
prefix="| ",
postfix=" |",
wrapfunc=lambda x: wrapper(x, width),
)
)
# output:
#
# Without wrapping function
#
# First Name | Last Name | Age | Position
# -------------------------------------------------------
# John | Smith | 24 | Software Engineer
# Mary | Brohowski | 23 | Sales Manager
# Aristidis | Papageorgopoulos | 28 | Senior Reseacher
#
# Wrapping function: wrap_always(x,width=10)
#
# ----------------------------------------------
# | First Name | Last Name | Age | Position |
# ----------------------------------------------
# | John | Smith | 24 | Software E |
# | | | | ngineer |
# ----------------------------------------------
# | Mary | Brohowski | 23 | Sales Mana |
# | | | | ger |
# ----------------------------------------------
# | Aristidis | Papageorgo | 28 | Senior Res |
# | | poulos | | eacher |
# ----------------------------------------------
#
# Wrapping function: wrap_onspace(x,width=10)
#
# ---------------------------------------------------
# | First Name | Last Name | Age | Position |
# ---------------------------------------------------
# | John | Smith | 24 | Software |
# | | | | Engineer |
# ---------------------------------------------------
# | Mary | Brohowski | 23 | Sales |
# | | | | Manager |
# ---------------------------------------------------
# | Aristidis | Papageorgopoulos | 28 | Senior |
# | | | | Reseacher |
# ---------------------------------------------------
#
# Wrapping function: wrap_onspace_strict(x,width=10)
#
# ---------------------------------------------
# | First Name | Last Name | Age | Position |
# ---------------------------------------------
# | John | Smith | 24 | Software |
# | | | | Engineer |
# ---------------------------------------------
# | Mary | Brohowski | 23 | Sales |
# | | | | Manager |
# ---------------------------------------------
# | Aristidis | Papageorgo | 28 | Senior |
# | | poulos | | Reseacher |
# ---------------------------------------------
데이터를 준비하여 실제에 전달할 수 있습니다.column
효용.
데이터를 /tmp/filename 파일에 인쇄했다고 가정합니다.txt와 탭을 delimeter로 지정합니다.그런 다음 다음과 같이 열화할 수 있습니다.
import subprocess
result = subprocess.run("cat /tmp/filename.txt | column -N \"col_1,col_2,col_3\" -t -s'\t' -R 2,3", shell=True, stdout=subprocess.PIPE)
print(result.stdout.decode("utf-8"))
보시다시피 오른쪽 정렬과 같은 열 유틸리티 기능을 사용할 수 있습니다.
table = [['a', 'b', 'c'],
['aaaaaaaaaa', 'b', 'c'],
['a', 'bbbbbbbbbb', 'c']]
def print_table(table):
def get_fmt(table):
fmt = ''
for column, row in enumerate(table[0]):
fmt += '{{!s:<{}}} '.format(
max(len(str(row[column])) for row in table) + 2)
return fmt
fmt = get_fmt(table)
for row in table:
print(fmt.format(*row))
print_table(table)
이건 재미있는 작은 프로젝트였는데...
컬럼을 클릭합니다.화이
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import Iterable, Iterator, Sequence, Sized
Matrix = Sequence[Sequence]
def all_elem_same_length(list: Sequence) -> bool:
length = len(list[0])
for elem in list:
if not len(elem) == length:
return False
return True
def get_col(matrix: Matrix, col_i: int) -> Iterator[Sized]:
return (row[col_i] for row in matrix)
def get_cols(matrix: Matrix) -> Iterator[Iterable[Sized]]:
return (get_col(matrix, col_i) for col_i in range(len(matrix[0])))
def get_longest_elem(list: Iterable[Sized]) -> Sized:
return max(list, key=len)
def get_longest_elem_per_column(matrix: Matrix) -> Iterator[Sized]:
return (get_longest_elem(col) for col in get_cols(matrix))
def get_word_pad_fstr(element: Sized, padding: int) -> str:
return f"{{:{len(element)+padding}}}"
def get_row_elem_pad_strings(matrix: Matrix, padding: int) -> Iterator[str]:
return (
get_word_pad_fstr(word, padding) for word in get_longest_elem_per_column(matrix)
)
def print_table(matrix: Matrix, padding=4) -> None:
if not all_elem_same_length(matrix):
raise ValueError("Table rows must all have the same length.")
format_string = "".join(get_row_elem_pad_strings(matrix, padding))
for row in matrix:
print(format_string.format(*(str(e) for e in row)))
if __name__ == "__main__":
data = [["a", "b", "c"], ["aaaaaaaa", "b", "c"], ["a", "bbbbbbbbbb", "ccc"]]
print_table(data)
오래된 질문인 것은 알지만, Antak의 답변을 이해하지 못했고, 도서관을 이용하기 싫어서 나만의 해결책을 제시했습니다.
솔루션은 레코드가 2D 어레이이고 레코드의 길이가 모두 동일하며 필드가 모두 문자열이라고 가정합니다.
def stringifyRecords(records):
column_widths = [0] * len(records[0])
for record in records:
for i, field in enumerate(record):
width = len(field)
if width > column_widths[i]: column_widths[i] = width
s = ""
for record in records:
for column_width, field in zip(column_widths, record):
s += field.ljust(column_width+1)
s += "\n"
return s
저는 이 답변이 매우 도움이 되고 우아하다는 것을 알았습니다.원래는 여기서부터입니다.
matrix = [["A", "B"], ["C", "D"]]
print('\n'.join(['\t'.join([str(cell) for cell in row]) for row in matrix]))
산출량
A B
C D
언급URL : https://stackoverflow.com/questions/9989334/create-nice-column-output-in-python
'programing' 카테고리의 다른 글
PowerShell의 Clear-History가 이력을 클리어하지 않음 (0) | 2023.04.14 |
---|---|
빠르고 슬림한 iPhone/iPad/iOS용 PDF 뷰어 - 힌트? (0) | 2023.04.14 |
Swift에서 "포장되지 않은 가치"란 무엇입니까? (0) | 2023.04.09 |
Swift 5.1로 컴파일된 모듈은 Swift 5.1.2 컴파일러에서 가져올 수 없습니다. (0) | 2023.04.09 |
git에서 복제된 프로젝트에서 버전 추적을 제거하려면 어떻게 해야 합니까? (0) | 2023.04.09 |