输出列表如ls

时间:2014-07-29 23:29:52

标签: python pprint

this相同的问题,但对于python。如果我有一个清单

['a','b','cdefg','jk','lmnopqr','st','uv','wxyz',1,2,3,4]

我想在bash中打印类似于ls命令的默认输出,类似于

[ 'a',   'b',        'cdefg',
  'jk',  'st',       'lm',
  'no',  'pqrstuv',  'wxyz',  
  1,     2,          3,
  4,     ]

目标是一次在屏幕上最大化可视分析数据。我只能找到pprint库,对于简单列表,它可以打印为默认值,也可以打印每行一个。这样的事情是否存在?

2 个答案:

答案 0 :(得分:3)

感谢大家的想法,并澄清确实没有现成的解决方案。我编码了我想要的,代码如下。在宽度为80个字符的终端

pprint_list( [ string.lowercase[i % 26]*random.randint(1,20) for i in range(8) ] )

打印为

[ 'aaaa',         'bbbbbbbbbbbbbbb',   'ccccccccccccccccccc',  'd',  
  'eeeeeeeeeee',  'ffffffffffffffff',  'gggggggggggggggg',     'h'   ]

查看代码显示,显然有一些开销计算如何调整列的大小,更多的条目和更宽的终端需要更多的计算,但将条目数从8移到50000并没有多少滞后时间,所以我觉得我很满意。

此代码依赖于get_terminal_size函数here

#!/usr/bin/env python
def pprint_list(input_list):
    (term_width, term_height) = get_terminal_size()
    if len( str(input_list) ) <= term_width:
        print input_list
        return

    repr_list = [repr(x) for x in input_list]
    min_chars_between = 3 # a comma and two spaces
    usable_term_width = term_width - 3 # For '[ ' and ']' at beginning and end
    min_element_width = min( len(x) for x in repr_list ) + min_chars_between
    max_element_width = max( len(x) for x in repr_list ) + min_chars_between
    if max_element_width >= usable_term_width:
        ncol = 1
        col_widths = [1]
    else:
        # Start with max possible number of columns and reduce until it fits
        ncol = min( len(repr_list), usable_term_width / min_element_width  )
        while True:
            col_widths = [ max( len(x) + min_chars_between \
                                for j, x in enumerate( repr_list ) if j % ncol == i ) \
                                for i in range(ncol) ]
            if sum( col_widths ) <= usable_term_width: break
            else: ncol -= 1

    sys.stdout.write('[ ')
    for i, x in enumerate(repr_list):
        if i != len(repr_list)-1: x += ','
        sys.stdout.write( x.ljust( col_widths[ i % ncol ] ) )
        if i == len(repr_list) - 1:
            sys.stdout.write(']\n')
        elif (i+1) % ncol == 0:
            sys.stdout.write('\n  ')

答案 1 :(得分:2)

def columnify(iterable):
    # First convert everything to its repr
    strings = [repr(x) for x in iterable]
    # Now pad all the strings to match the widest
    widest = max(len(x) for x in strings)
    padded = [x.ljust(widest) for x in strings]
    return padded

现在,您应该可以使用pprint.pprint(compact=True)textwrap或其他工具来获取所需的格式。

但是如果你想手动完成,那么做任何你想做的事情并不难。例如:

def colprint(iterable, width=72):
    columns = columnify(iterable)
    colwidth = len(columns[0])+2
    perline = (width-4) // colwidth
    print('[ ', end='')
    for i, column in enumerate(columns):
        print(column, end=', ')
        if i % perline == perline-1:
            print('\n  ', end='')
    print(' ]')

所以:

>>> arr = ['a', 'b', 'cdefg', 'jk', 'lmnopqr', 'st', 'uv', 'wxyz', 1, 2, 3, 4]
>>> colprint(arr, 60)
[ 'a'      , 'b'      , 'cdefg'  , 'jk'     , 'lmnopqr',
  'st'     , 'uv'     , 'wxyz'   , 1        , 2        ,
  3        , 4        ,  ]

这仍然不能准确地告诉你ls的作用;例如,ls有一些启发式方法可以确保文件名太长&#34;不要计入最大宽度,而是跨越多列。如果你真的想要完成与ls相同的所有 ,你可能需要查看源代码并从C转换为Python ......

另外,请查看pprint。每当模块的文档以源代码的链接开始时,这意味着该模块可以作为有用的示例代码,并且可以自己使用。因此,如果您想查看它用于确定何时分割线的规则(基于compact标志以及宽度),您应该能够从中找出它。