创建行为类似于 table 的格式化字符串输出的简单方法
Simple way to create formatted string output that behaves like table
在我去重新发明轮子之前,我想检查一下是否有人已经为此想出了一些办法。
我有一个字符串列表,需要以 table 格式打印出来。我从 tables 中获取数据,这些数据在某些单元格中可能包含较长的数据字符串。
如果我尝试根据最长的字符串设置列宽,我最终可能会得到巨大的列宽。
我想知道是否已经存在一些东西可以将字符串数据附加到仍然与当前行对齐的另一行(基本上将其视为强制自动填充的单元格)
示例
listObj = ['Pre-Condition:', 'Condition:', 'Output:',
'Button is OFF', '-', 'Speed is not on',
'Button Enabled is OFF', 'Enabled is ON',
'Speed is on', 'Button Active is ON', 'Active is OFF',
'Hold steady true north', 'Button States is HOLD',
'Button States is ACCELERATOR OVERRIDE AND Set stuff is on <Stuff here>',
'Pedal to the medal here guys']
上面的列表原本是一个三乘五的列表table。所以我想以三列的形式打印所有内容。我 运行 进入问题的地方是列表中倒数第二个字符串项。还有更多类似的例子,因为这是一个有点人为的例子。任何帮助将不胜感激。我以前 运行 遇到过这个问题,所以我想问一下,因为我确定其他人也遇到过这个问题。
想要的结果
Pre-Condition Condition Output
Button is OFF - Speed is not on
Button Enabled is OFF Active is OFF Speed is on
Button States is HOLD Button states is Pedal to the med
ACCELERATOR OVERRIDE here guys
AND Set stuff is on
编辑:使用 list 作为变量,我一直用它搬起石头砸自己的脚
这是对您所寻找内容的硬编码尝试。范围的错误检查也很少。我会让你处理:)
mylist = ['Pre-Condition:', 'Condition:', 'Output:',
'Button is OFF', '-', 'Speed is not on',
'Button Enabled is OFF', 'Enabled is ON',
'Speed is on', 'Button Active is ON', 'Active is OFF',
'Hold steady true north', 'Button States is HOLD',
'Button States is ACCELERATOR OVERRIDE AND Set stuff is on <Stuff here>',
'Pedal to the medal here guys']
def printCell(row, cellWidth):
while row != ["","",""]:
lineformat = ("{:"+str(cellWidth) + "} | ") * 3
cells=[]
for n, cell in enumerate(row):
p = cellWidth
if len(cell) > cellWidth :
p = cell[:cellWidth].rfind(" ")
if p == -1:
p = cellWidth
row[n] = cell[p:]
else:
row[n] = ""
cells.append(cell[:p])
print(lineformat.format(*cells))
def printColumns(alist, colCount, colWidth):
for n in range(0,len(alist)-1,colCount):
printCell(alist[n:n+colCount], colWidth)
print("-" * colWidth * colCount)
if __name__ == "__main__":
printColumns(mylist,3,30)
输出:
Pre-Condition: | Condition: | Output: |
------------------------------------------------------------------------------------------
Button is OFF | - | Speed is not on |
------------------------------------------------------------------------------------------
Button Enabled is OFF | Enabled is ON | Speed is on |
------------------------------------------------------------------------------------------
Button Active is ON | Active is OFF | Hold steady true north |
------------------------------------------------------------------------------------------
Button States is HOLD | Button States is ACCELERATOR | Pedal to the medal here guys |
| OVERRIDE AND Set stuff is on | |
| <Stuff here> | |
------------------------------------------------------------------------------------------
编辑
为什么不创建一个可以直接用 excel 打开的 csv 文件?
import csv
with open('output.csv', 'w') as f:
csvOut = csv.writer(f, delimiter=',')
for n in range(0,len(mylist)-1,3):
csvOut.writerow(mylist[n:n+3])
旁注
使用 'list' 作为变量是错误的形式。这可能会与内置列表类型发生冲突,应该避免。
这是一种非常灵活的方法:
# a simple function to do our line-splitting per value
def split_value(value, width):
result = []
while len(value) > width: # while our string is longer than allowed
split_index = value.rfind(" ", 0, width)
if split_index == -1: # no space in our current chunk, we must do hard-break
split_index = width - 1 # set the split to our column width point
result.append(value[:split_index + 1]) # add the current slice as a sub-row
value = value[split_index + 1:] # remove the added slice from our data
if value: # there are leftovers from slicing, add them as the last piece
result.append(value)
return result
# and our main function...
def draw_table(data, columns, table_width, column_border=1):
column_data = [data[i::columns] for i in range(columns)] # split the data into columns
column_width = table_width // columns - column_border # max characters per column
column_template = ("{} " * (columns - 1)) + "{}" # a simple template for our columns
empty_value = " " * (column_width + column_border) # what to print when there's no value
rows = len(max(column_data, key=len)) # in case we have more data in some of the columns
for row in range(rows): # lets print our rows
row_data = [split_value(x[row], column_width) if len(x) > row else []
for x in column_data] # lets populate our row
subrows = len(max(row_data, key=len)) # number of subrows for the current row
for subrow in range(subrows): # lets go through each of them and print them out
print(column_template.format(*[x[subrow].ljust(column_width+column_border)
if len(x) > subrow else empty_value
for x in row_data])) # print our (split) row
它有点扭曲,但可以可靠地完成工作,如果您阅读评论,理解起来并不难。它应该完全符合您的要求(您想要的结果似乎不符合您列表中的数据):
listObj = ['Pre-Condition:', 'Condition:', 'Output:',
'Button is OFF', '-', 'Speed is not on',
'Button Enabled is OFF', 'Enabled is ON',
'Speed is on', 'Button Active is ON', 'Active is OFF',
'Hold steady true north', 'Button States is HOLD',
'Button States is ACCELERATOR OVERRIDE AND Set stuff is on <Stuff here>',
'Pedal to the medal here guys']
# table with three columns, two spaces between columns and of total width of 80 characters
draw_table(listObj, 3, 80, 2)
生产:
Pre-Condition: Condition: Output:
Button is OFF - Speed is not on
Button Enabled is OFF Enabled is ON Speed is on
Button Active is ON Active is OFF Hold steady true north
Button States is HOLD Button States is Pedal to the medal here
ACCELERATOR OVERRIDE guys
AND Set stuff is on
<Stuff here>
作为奖励,它支持不均匀列表,因此您可以执行以下操作:
listObj = ['Pre-Condition:', 'Condition:', 'Output:',
'Button is OFF', '-', 'Speed is not on',
'Button Enabled is OFF', 'Enabled is ON',
'Speed is on', 'Button Active is ON', 'Active is OFF',
'Hold steady true north', 'Button States is HOLD',
'Button States is ACCELERATOR OVERRIDE AND Set stuff is on...',
'Pedal to the medal here guys', "One extra value to prove the flow"]
draw_table(listObj, 3, 80, 2)
这将产生:
Pre-Condition: Condition: Output:
Button is OFF - Speed is not on
Button Enabled is OFF Enabled is ON Speed is on
Button Active is ON Active is OFF Hold steady true north
Button States is HOLD Button States is Pedal to the medal here
ACCELERATOR OVERRIDE guys
AND Set stuff is on...
One extra value to
prove the flow
像可变列宽这样的未来升级应该不会那么困难,因为行数据拆分是外部的,因此可以添加任何大小。
在我去重新发明轮子之前,我想检查一下是否有人已经为此想出了一些办法。
我有一个字符串列表,需要以 table 格式打印出来。我从 tables 中获取数据,这些数据在某些单元格中可能包含较长的数据字符串。
如果我尝试根据最长的字符串设置列宽,我最终可能会得到巨大的列宽。
我想知道是否已经存在一些东西可以将字符串数据附加到仍然与当前行对齐的另一行(基本上将其视为强制自动填充的单元格)
示例
listObj = ['Pre-Condition:', 'Condition:', 'Output:',
'Button is OFF', '-', 'Speed is not on',
'Button Enabled is OFF', 'Enabled is ON',
'Speed is on', 'Button Active is ON', 'Active is OFF',
'Hold steady true north', 'Button States is HOLD',
'Button States is ACCELERATOR OVERRIDE AND Set stuff is on <Stuff here>',
'Pedal to the medal here guys']
上面的列表原本是一个三乘五的列表table。所以我想以三列的形式打印所有内容。我 运行 进入问题的地方是列表中倒数第二个字符串项。还有更多类似的例子,因为这是一个有点人为的例子。任何帮助将不胜感激。我以前 运行 遇到过这个问题,所以我想问一下,因为我确定其他人也遇到过这个问题。
想要的结果
Pre-Condition Condition Output Button is OFF - Speed is not on Button Enabled is OFF Active is OFF Speed is on Button States is HOLD Button states is Pedal to the med ACCELERATOR OVERRIDE here guys AND Set stuff is on
编辑:使用 list 作为变量,我一直用它搬起石头砸自己的脚
这是对您所寻找内容的硬编码尝试。范围的错误检查也很少。我会让你处理:)
mylist = ['Pre-Condition:', 'Condition:', 'Output:',
'Button is OFF', '-', 'Speed is not on',
'Button Enabled is OFF', 'Enabled is ON',
'Speed is on', 'Button Active is ON', 'Active is OFF',
'Hold steady true north', 'Button States is HOLD',
'Button States is ACCELERATOR OVERRIDE AND Set stuff is on <Stuff here>',
'Pedal to the medal here guys']
def printCell(row, cellWidth):
while row != ["","",""]:
lineformat = ("{:"+str(cellWidth) + "} | ") * 3
cells=[]
for n, cell in enumerate(row):
p = cellWidth
if len(cell) > cellWidth :
p = cell[:cellWidth].rfind(" ")
if p == -1:
p = cellWidth
row[n] = cell[p:]
else:
row[n] = ""
cells.append(cell[:p])
print(lineformat.format(*cells))
def printColumns(alist, colCount, colWidth):
for n in range(0,len(alist)-1,colCount):
printCell(alist[n:n+colCount], colWidth)
print("-" * colWidth * colCount)
if __name__ == "__main__":
printColumns(mylist,3,30)
输出:
Pre-Condition: | Condition: | Output: |
------------------------------------------------------------------------------------------
Button is OFF | - | Speed is not on |
------------------------------------------------------------------------------------------
Button Enabled is OFF | Enabled is ON | Speed is on |
------------------------------------------------------------------------------------------
Button Active is ON | Active is OFF | Hold steady true north |
------------------------------------------------------------------------------------------
Button States is HOLD | Button States is ACCELERATOR | Pedal to the medal here guys |
| OVERRIDE AND Set stuff is on | |
| <Stuff here> | |
------------------------------------------------------------------------------------------
编辑
为什么不创建一个可以直接用 excel 打开的 csv 文件?
import csv
with open('output.csv', 'w') as f:
csvOut = csv.writer(f, delimiter=',')
for n in range(0,len(mylist)-1,3):
csvOut.writerow(mylist[n:n+3])
旁注
使用 'list' 作为变量是错误的形式。这可能会与内置列表类型发生冲突,应该避免。
这是一种非常灵活的方法:
# a simple function to do our line-splitting per value
def split_value(value, width):
result = []
while len(value) > width: # while our string is longer than allowed
split_index = value.rfind(" ", 0, width)
if split_index == -1: # no space in our current chunk, we must do hard-break
split_index = width - 1 # set the split to our column width point
result.append(value[:split_index + 1]) # add the current slice as a sub-row
value = value[split_index + 1:] # remove the added slice from our data
if value: # there are leftovers from slicing, add them as the last piece
result.append(value)
return result
# and our main function...
def draw_table(data, columns, table_width, column_border=1):
column_data = [data[i::columns] for i in range(columns)] # split the data into columns
column_width = table_width // columns - column_border # max characters per column
column_template = ("{} " * (columns - 1)) + "{}" # a simple template for our columns
empty_value = " " * (column_width + column_border) # what to print when there's no value
rows = len(max(column_data, key=len)) # in case we have more data in some of the columns
for row in range(rows): # lets print our rows
row_data = [split_value(x[row], column_width) if len(x) > row else []
for x in column_data] # lets populate our row
subrows = len(max(row_data, key=len)) # number of subrows for the current row
for subrow in range(subrows): # lets go through each of them and print them out
print(column_template.format(*[x[subrow].ljust(column_width+column_border)
if len(x) > subrow else empty_value
for x in row_data])) # print our (split) row
它有点扭曲,但可以可靠地完成工作,如果您阅读评论,理解起来并不难。它应该完全符合您的要求(您想要的结果似乎不符合您列表中的数据):
listObj = ['Pre-Condition:', 'Condition:', 'Output:',
'Button is OFF', '-', 'Speed is not on',
'Button Enabled is OFF', 'Enabled is ON',
'Speed is on', 'Button Active is ON', 'Active is OFF',
'Hold steady true north', 'Button States is HOLD',
'Button States is ACCELERATOR OVERRIDE AND Set stuff is on <Stuff here>',
'Pedal to the medal here guys']
# table with three columns, two spaces between columns and of total width of 80 characters
draw_table(listObj, 3, 80, 2)
生产:
Pre-Condition: Condition: Output: Button is OFF - Speed is not on Button Enabled is OFF Enabled is ON Speed is on Button Active is ON Active is OFF Hold steady true north Button States is HOLD Button States is Pedal to the medal here ACCELERATOR OVERRIDE guys AND Set stuff is on <Stuff here>
作为奖励,它支持不均匀列表,因此您可以执行以下操作:
listObj = ['Pre-Condition:', 'Condition:', 'Output:',
'Button is OFF', '-', 'Speed is not on',
'Button Enabled is OFF', 'Enabled is ON',
'Speed is on', 'Button Active is ON', 'Active is OFF',
'Hold steady true north', 'Button States is HOLD',
'Button States is ACCELERATOR OVERRIDE AND Set stuff is on...',
'Pedal to the medal here guys', "One extra value to prove the flow"]
draw_table(listObj, 3, 80, 2)
这将产生:
Pre-Condition: Condition: Output: Button is OFF - Speed is not on Button Enabled is OFF Enabled is ON Speed is on Button Active is ON Active is OFF Hold steady true north Button States is HOLD Button States is Pedal to the medal here ACCELERATOR OVERRIDE guys AND Set stuff is on... One extra value to prove the flow
像可变列宽这样的未来升级应该不会那么困难,因为行数据拆分是外部的,因此可以添加任何大小。