【问题标题】:Line up columns of numbers (print output in table format)排列数字列(以表格格式打印输出)
【发布时间】:2010-09-10 14:04:36
【问题描述】:

我有以下格式的数据(数字)(示例):

234 127 34 23 45567  
23 12 4 4 45  
23456 2 1 444 567  
...

有没有python方式的方法来排列数字并将它们作为

  234  127  34   23  45567  
   23   12   4    4     45  
23456    2   1  444    567 

(我无法预测列大小)。

【问题讨论】:

标签: python


【解决方案1】:

这是一个简单的、独立的示例,展示了如何设置可变列宽的格式:

data = '''\
234 127 34 23 45567
23 12 4 4 45
23456 2 1 444 567'''

# Split input data by row and then on spaces
rows = [ line.strip().split(' ') for line in data.split('\n') ]

# Reorganize data by columns
cols = zip(*rows)

# Compute column widths by taking maximum length of values per column
col_widths = [ max(len(value) for value in col) for col in cols ]

# Create a suitable format string
format = ' '.join(['%%%ds' % width for width in col_widths ])

# Print each row using the computed format
for row in rows:
  print format % tuple(row)

哪个输出:

  234 127 34  23 45567
   23  12  4   4    45
23456   2  1 444   567

【讨论】:

  • 谢谢。 FWIW 我通过使用'%%-%ds' 生成格式字符串使列左对齐
  • 这里是新样式格式的相关部分,左对齐: fmt = ' '.join(['{{:
【解决方案2】:

您需要一些方法来查找列大小, 也许通过读取所有数据并找到最大宽度。

>>> line='234 127 34 23 45567'
>>> line.split()
['234', '127', '34', '23', '45567']
>>> max(map(len, line.split()))
5

重复所有行,以找到列大小(例如,5)。 用percent formatting 构造一个格式化的行很简单。

>>> colsize = 5
>>> ' '.join(('%*s' % (colsize, i) for i in line.split()))
'  234   127    34    23 45567'
>>> 

【讨论】:

  • 不知道 '%*s'。好提示!
  • 问题是这些数字上线了,我不知道行数。为了使其更具可读性,我想将它们排列起来。就是这样。
  • 如果您无法计算最大宽度,请使用正确的猜测值,例如10.
【解决方案3】:
#!/usr/bin/env python

class ALIGN:
    LEFT, RIGHT = '-', ''

class Column(list):
    def __init__(self, name, data, align=ALIGN.RIGHT):
        list.__init__(self, data)
        self.name = name
        width = max(len(str(x)) for x in data + [name])
        self.format = ' %%%s%ds ' % (align, width)

class Table:
    def __init__(self, *columns):
        self.columns = columns
        self.length = max(len(x) for x in columns)
    def get_row(self, i=None):
        for x in self.columns:
            if i is None:
                yield x.format % x.name
            else:
                yield x.format % x[i]
    def get_rows(self):
        yield ' '.join(self.get_row(None))
        for i in range(0, self.length):
            yield ' '.join(self.get_row(i))

    def __str__(self):
        return '\n'.join(self.get_rows())   

你的例子:

if __name__ == '__main__':
    print Table(
        Column("", [234, 32, 23456]),
        Column("", [127, 12, 2]),
        Column("", [34, 4, 1]),
        Column("", [23, 4, 444]),
        Column("", [45567, 45, 567])
    )

它会产生:

   234   127   34    23   45567 
    32    12    4     4      45 
 23456     2    1   444     567 

改编自http://code.activestate.com/recipes/577202-render-tables-for-text-interface/

【讨论】:

  • 考虑到其他一些解决方案,这是令人难以置信的重量级。编写课程来处理这个问题有什么好处?
  • 但是这样更易读、更优雅,你不觉得吗?
【解决方案4】:
>>> rows = """234 127 34 23 45567
... 23 12 4 4 45
... 23456 2 1 444 567"""

首先将行转换为二维数组(列表列表)

>>> arr=[x.split() for x in rows.split("\n")]

现在计算每个字段需要适应的空间

>>> widths = [max(map(len,(f[i] for f in tab))) for i in range(len(arr[0]))]

并填充每个元素以适应该空间

>>> [[k.rjust(widths[i]) for i,k in enumerate(j)] for j in arr]
[['  234', '127', '34', ' 23', '45567'], ['   23', ' 12', ' 4', '  4', '   45'], ['23456', '  2', ' 1', '444', '  567']]

最后将数组重新连接成一个字符串

>>> print "\n".join("  ".join(k.rjust(widths[i]) for i,k in enumerate(j)) for j in arr)
  234  127  34   23  45567
   23   12   4    4     45
23456    2   1  444    567

【讨论】:

    【解决方案5】:

    【讨论】:

      【解决方案6】:

      d前面的整数是整数将在前一列之后开始的列 编号,以便您可以按照您认为合适的方式排列它们

      print("{0:4d} {1:4d} {2:4d} {3:4d} {4:4d}".format(234, 127, 34, 23, 45567))

      必要时重复

      【讨论】:

        【解决方案7】:

        Kevin Jacobs 的回答修改为允许a variable number of integers on each row

        def align(data, delimiter = '\t', is_left_align = True):
          rows = [row.strip().split(delimiter) for row in data.split('\n')]
          cols = map(lambda *row: [str(field) or '' for field in row], *rows)
          widths = [max(len(field) for field in col) for col in cols]
          format = ['%%%s%ds' % ('-' if is_left_align else '', width) for width in widths]
          return '\n'.join([delimiter.join(format[:len(row)]) % tuple(row) for row in rows])
        
        data = '''\
        234 127 34 23 45567
        23 12 4 4 45
        23456 2 1 444 567'''
        print(align(data, ' ', False))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-05
          • 1970-01-01
          • 1970-01-01
          • 2021-12-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多