如何更好地打印列表?

时间:2009-10-06 07:43:59

标签: python printing

这类似于How to print a list in Python “nicely”,但我想更清楚地打印列表 - 没有括号和撇号和逗号,甚至更好的列。

foolist = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf', 
    'pdcurses-devel',     'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel', 
    'qgis1.1', 'php_mapscript']

evenNicerPrint(foolist)

期望的结果:

exiv2-devel       msvcrt        
mingw-libs        gdal-grass    
tcltk-demos       iconv         
fcgi              qgis-devel    
netcdf            qgis1.1       
pdcurses-devel    php_mapscript 

谢谢!

23 个答案:

答案 0 :(得分:19)

这个答案在@Aaron Digulla的回答中使用了相同的方法,语法略高于pythonic。它可能使上述一些答案更容易理解。

>>> for a,b,c in zip(foolist[::3],foolist[1::3],foolist[2::3]):
>>>     print '{:<30}{:<30}{:<}'.format(a,b,c)

exiv2-devel                   mingw-libs                    tcltk-demos
fcgi                          netcdf                        pdcurses-devel
msvcrt                        gdal-grass                    iconv
qgis-devel                    qgis1.1                       php_mapscript

这可以很容易地适应任意数量的列或变量列,这将导致类似@gnibbler的答案。可以根据屏幕宽度调整间距。


更新:按要求说明。

<强>索引

foolist[::3]选择foolist的每个第三个元素。 foolist[1::3]从第二个元素('1'开始选择每个第三个元素,因为python使用零索引)。

In [2]: bar = [1,2,3,4,5,6,7,8,9]
In [3]: bar[::3]
Out[3]: [1, 4, 7]

<强>拉链

压缩列表(或其他迭代)生成列表元素的元组。例如:

In [5]: zip([1,2,3],['a','b','c'],['x','y','z'])
Out[5]: [(1, 'a', 'x'), (2, 'b', 'y'), (3, 'c', 'z')]

<强>一起

将这些想法放在一起我们得到了解决方案:

for a,b,c in zip(foolist[::3],foolist[1::3],foolist[2::3]):

这里我们首先生成foolist的三个“切片”,每个切片由每第三个元素索引并偏移一个。它们各自只包含列表的三分之一。现在,当我们压缩这些切片并进行迭代时,每次迭代都会给出三个foolist元素。

我们想要的是:

In [11]: for a,b,c in zip(foolist[::3],foolist[1::3],foolist[2::3]):
   ....:      print a,b,c                           
Out[11]: exiv2-devel mingw-libs tcltk-demos
         fcgi netcdf pdcurses-devel
        [etc]

而不是:

In [12]: for a in foolist: 
   ....:     print a
Out[12]: exiv2-devel
         mingw-libs
         [etc]

答案 1 :(得分:11)

简单:

l = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf', 
    'pdcurses-devel',     'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel', 
    'qgis1.1', 'php_mapscript']

if len(l) % 2 != 0:
    l.append(" ")

split = len(l)/2
l1 = l[0:split]
l2 = l[split:]
for key, value in zip(l1,l2):
    print '%-20s %s' % (key, value)         #python <2.6
    print "{0:<20s} {1}".format(key, value) #python 2.6+

答案 2 :(得分:8)

受到gimel的回答的启发,above

import math

def list_columns(obj, cols=4, columnwise=True, gap=4):
    """
    Print the given list in evenly-spaced columns.

    Parameters
    ----------
    obj : list
        The list to be printed.
    cols : int
        The number of columns in which the list should be printed.
    columnwise : bool, default=True
        If True, the items in the list will be printed column-wise.
        If False the items in the list will be printed row-wise.
    gap : int
        The number of spaces that should separate the longest column
        item/s from the next column. This is the effective spacing
        between columns based on the maximum len() of the list items.
    """

    sobj = [str(item) for item in obj]
    if cols > len(sobj): cols = len(sobj)
    max_len = max([len(item) for item in sobj])
    if columnwise: cols = int(math.ceil(float(len(sobj)) / float(cols)))
    plist = [sobj[i: i+cols] for i in range(0, len(sobj), cols)]
    if columnwise:
        if not len(plist[-1]) == cols:
            plist[-1].extend(['']*(len(sobj) - len(plist[-1])))
        plist = zip(*plist)
    printer = '\n'.join([
        ''.join([c.ljust(max_len + gap) for c in p])
        for p in plist])
    print printer

结果(第二个满足您的要求):

>>> list_columns(foolist)
exiv2-devel       fcgi              msvcrt            qgis-devel        
mingw-libs        netcdf            gdal-grass        qgis1.1           
tcltk-demos       pdcurses-devel    iconv             php_mapscript     

>>> list_columns(foolist, cols=2)
exiv2-devel       msvcrt            
mingw-libs        gdal-grass        
tcltk-demos       iconv             
fcgi              qgis-devel        
netcdf            qgis1.1           
pdcurses-devel    php_mapscript     

>>> list_columns(foolist, columnwise=False)
exiv2-devel       mingw-libs        tcltk-demos       fcgi              
netcdf            pdcurses-devel    msvcrt            gdal-grass        
iconv             qgis-devel        qgis1.1           php_mapscript     

>>> list_columns(foolist, gap=1)
exiv2-devel    fcgi           msvcrt         qgis-devel     
mingw-libs     netcdf         gdal-grass     qgis1.1        
tcltk-demos    pdcurses-devel iconv          php_mapscript  

答案 3 :(得分:5)

请参阅formatting-a-list-of-text-into-columns

一般解决方案,处理任意数量的列和奇数列表。 制表符分隔列,使用生成器表达式来节省空间。

def fmtcols(mylist, cols):
    lines = ("\t".join(mylist[i:i+cols]) for i in xrange(0,len(mylist),cols))
    return '\n'.join(lines)

答案 4 :(得分:5)

Aaron的做法可以使用两列以上

答案 5 :(得分:3)

如果数据采用您提供的格式,则需要更多工作


>>> d = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf', 
...     'pdcurses-devel',     'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel', 
...     'qgis1.1', 'php_mapscript']
>>> print "\n".join("%-20s %s"%(d[i],d[i+len(d)/2]) for i in range(len(d)/2))
exiv2-devel          msvcrt
mingw-libs           gdal-grass
tcltk-demos          iconv
fcgi                 qgis-devel
netcdf               qgis1.1
pdcurses-devel       php_mapscript

答案 6 :(得分:1)

我使用 IPython 内部 columnize function

import IPython
foolist = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf', 
           'pdcurses-devel', 'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel', 
           'qgis1.1', 'php_mapscript']

foolist_columnized = IPython.utils.text.columnize(foolist)
print(foolist_columnized)

输出将如下所示:

exiv2-devel  tcltk-demos  netcdf          msvcrt      iconv       qgis1.1
mingw-libs   fcgi         pdcurses-devel  gdal-grass  qgis-devel  php_mapscript

答案 7 :(得分:1)

这是我的解决方案。 (Copy in GitHub gist

它将终端宽度作为输入,并且只显示可以容纳的列数。

def col_print(lines, term_width=80, indent=0, pad=2):
  n_lines = len(lines)
  if n_lines == 0:
    return

  col_width = max(len(line) for line in lines)
  n_cols = int((term_width + pad - indent)/(col_width + pad))
  n_cols = min(n_lines, max(1, n_cols))

  col_len = int(n_lines/n_cols) + (0 if n_lines % n_cols == 0 else 1)
  if (n_cols - 1) * col_len >= n_lines:
    n_cols -= 1

  cols = [lines[i*col_len : i*col_len + col_len] for i in range(n_cols)]

  rows = list(zip(*cols))
  rows_missed = zip(*[col[len(rows):] for col in cols[:-1]])
  rows.extend(rows_missed)

  for row in rows:
    print(" "*indent + (" "*pad).join(line.ljust(col_width) for line in row))

答案 8 :(得分:1)

我将n列解决方案扩展到@Aman的答案

def printMultiCol(l, n_cols, buffer_len=5):
    """formats a list of strings, l, into n_cols with a separation of buffer_len"""
    if not l: return [] # return if not iterable!
    max_l = max(map(len, l))
    formatter = '{{:<{max_l}}}'.format(max_l=max_l+buffer_len)*n_cols
    zip_me_up = [l[i::n_cols] for i in xrange(n_cols)]
    max_zip_l = max(map(len, zip_me_up))
    zip_me_up = map(lambda x: x + ['']*(max_zip_l-len(x)), zip_me_up)
    return [formatter.format(*undress_me) for undress_me in zip(*zip_me_up)]

测试

使用随机字符串长度设置测试

import random
list_length = 16
random_strings = [
    ''.join(random.choice('spameggsbaconbeanssausage') 
    for x in range(random.randint(1,10)))
    for i in xrange(list_length)
]

print 'for 4 columns (equal length cols) ...\n{}'.format(
    '\n'.join(printMultiCol(random_strings, 4))
)
print 'for 7 columns (odd length cols) ...\n{}'.format(
    '\n'.join(printMultiCol(random_strings, 5))
)

返回

## -- End pasted text --
for 4 columns (equal length cols) ...
sgsebpasgm     assgaesse      ossmeagan      ebesnagec
mees           eeges          m              gcb
sm             pbe            bbgaa          ganopabnn
bmou           asbegu         a              psoge


for 7 columns (odd length cols) ...
sgsebpasgm     assgaesse      ossmeagan      ebesnagec      mees
eeges          m              gcb            sm             pbe
bbgaa          ganopabnn      bmou           asbegu         a
psoge

答案 9 :(得分:1)

这样的事情怎么样?

def strlistToColumns( strl, maxWidth, spacing=4 ):

longest = max([len(s) for s in strl])
width = longest+spacing

# compute numCols s.t. (numCols-1)*(longest+spacing)+longest < maxWidth
numCols = 1 + (maxWidth-longest)//width
C = range(numCols)

# If len(strl) does not have a multiple of numCols, pad it with empty strings
strl += [""]*(len(strl) % numCols)
numRows = len(strl)/numCols
colString = ''

for r in range(numRows):
    colString += "".join(["{"+str(c)+":"+str(width)+"}" \
        for c in C]+["\n"]).format(*(strl[numCols*r+c] \
        for c in C))

return colString 


if __name__ == '__main__':

fruits = ['apple', 'banana', 'cantaloupe', 'durian', 'elderberry',         \
          'fig', 'grapefruit', 'honeydew', 'indonesian lime', 'jackfruit', \
          'kiwi', 'lychee', 'mango', 'orange', 'pomegranate', 'quince',    \
          'raspberry', 'tangerine', 'ugli fruit', 'watermelon', 'xigua',
          'yangmei', 'zinfandel grape']

cols = strlistToColumns( fruits, 80 )

print(cols)

<强>输出

apple              banana             cantaloupe         durian
elderberry         fig                grapefruit         honeydew
indonesian lime    jackfruit          kiwi               lychee
mango              orange             pomegranate        quince
raspberry          tangerine          ugli fruit         watermelon
xigua              yangmei            zinfandel grape

答案 10 :(得分:0)

对于 Python3,我使用 python - How do you split a list into evenly sized chunks? - Stack Overflow 创建

def chunkSectionList(listToPrint, columns):
    """ separate a list into chunks of n-items """
    for i in range(0, len(listToPrint), columns):
        yield listToPrint[i:i + columns]


def printSections(listToPrint, columns):
    remainder = len(listToPrint) % columns
    listToPrint += (columns - remainder) * \
        (" ") if remainder != 0 else listToPrint
    for sectionsLine in chunkSectionList(listToPrint, columns):
        formatStr = columns * '{:<30}'
        print(formatStr.format(* sectionsLine))

答案 11 :(得分:0)

这是简短方法

sigval

然后是 更好 方法,该方法可以关闭整个列表的恒定宽度,而不是优化各列的宽度,限制列数以适合最大每行显示字符数,或找到适合每行最大字符数的最佳列数,然后向左或向右强制对齐,并且仍然可以采用可选的格式字符串以及每列之间的间距宽度。

sigev_notify == SIGEV_THREAD

使用输出进行测试:

    header('Content-Type: image/png');
    $im = imagecreatefrompng('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png');
    imagepng($im);
    imagedestroy($im);

答案 12 :(得分:0)

对于Python> = 3.6,使用@JoshuaZastrowf-strings的答案稍作更新,并添加清除方法以调整列

cols = 5
[print(f'{key:20}', end='\t') if (idx + 1) % cols else print(f'{key}') for idx, key in enumerate(list_variable)]

cols = 5
for idx, key in enumerate(list_variable):
    if (idx + 1) % cols:
        print(f'{key:20}', end='\t')
    else:
        print(f'{key}')

答案 13 :(得分:0)

此人将列表打印在单独的列中(保留顺序)

from itertools import zip_longest

def ls(items, n_cols=2, pad=30):
    if len(items) == 0:
        return
    total = len(items)
    chunk_size = total // n_cols
    if chunk_size * n_cols < total:
        chunk_size += 1
    start = range(0, total, chunk_size)
    end = range(chunk_size, total + chunk_size, chunk_size)
    groups = (items[s:e] for s, e in zip(start, end))
    for group in zip_longest(*groups, fillvalue=''):
        template = (' ').join(['%%-%ds' % pad] * len(group))
        print(template % group)

用法:

ls([1, 2, 3, 4, 5, 6, 7], n_cols=3, pad=10)

输出:

1          4          7         
2          5                    
3          6                    

请注意,如果项数不足,则可能会缺少列,因为列会先填充。

ls([1, 2, 3, 4, 5], n_cols=4)

输出:

1          3          5         
2          4    

答案 14 :(得分:0)

这是一种直接的方法。请参阅内联注释以获取解释:

import shutil
import itertools
from functools import reduce


def split_list(lst, ncols):
    """Split list into rows"""
    return itertools.zip_longest(
        *[lst[i::ncols] for i in range(ncols)], fillvalue=""
    )
    # -- Alternatively --
    # import numpy as np
    # array = np.array(lst)
    # nrows = array.size / ncols + 1
    # return np.array_split(array, int(nrows))


def print_in_columns(lst):
    """Print a list in columns."""
    # Find maximum length of a string in colors_list
    colsize = reduce(lambda x, y: max(x, len(y)), lst, 0)
    # Terminal width
    maxcols = shutil.get_terminal_size()[0]
    ncols = maxcols / (colsize + 1)
    rows = split_list(lst, int(ncols))

    print(
        # Join rows
        "\n".join(
            (
                # Fill items left justified
                " ".join(item.ljust(colsize) for item in row)
                for row in rows
            )
        )
    )

答案 15 :(得分:0)

我需要调整每列。我已经实现了这段代码

qParc

示例:

def print_sorted_list(data, columns):
    if data:
        gap = 2
        ljusts = {}
        for count, item in enumerate(sorted(data), 1):
            column = count % columns
            ljusts[column] = len(item) if (column not in ljusts) else max(ljusts[column], len(item))

        for count, item in enumerate(sorted(data), 1):
            print item.ljust(ljusts[count % columns] + gap),
            if (count % columns == 0) or (count == len(data)):
                print

输出:

foolist = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf',
           'pdcurses-devel', 'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel',
           'qgis1.1', 'php_mapscript', 'blablablablablablabla', 'fafafafafafa']
print_sorted_list(foolist, 4)

答案 16 :(得分:0)

以下@Aman的扩展是一个函数,该函数获取字符串列表并根据终端大小按列输出它们。

import os
def column_display(input_list):
    '''
    Used to create a structured column display based on the users terminal size

    input_list : A list of string items which is desired to be displayed
    '''
    rows, columns = os.popen('stty size', 'r').read().split()
    terminal_space_eighth = int(columns)/8
    terminal_space_seventh = int(columns)/7
    terminal_space_sixth = int(columns)/6
    terminal_space_fifth = int(columns)/5
    terminal_space_quarter = int(columns)/4
    terminal_space_third = int(columns)/3
    terminal_space_half = int(columns)/2
    longest_string = max(input_list, key=len)
    longest_length = len(longest_string) + 1
    list_size = len(input_list)

    if longest_length > terminal_space_half:
         for string in input_list:
             print(string)
    elif terminal_space_eighth >= longest_length and list_size >= 8:
         for a,b,c,d,e,f,g,h in zip(input_list[::8],input_list[1::8],input_list[2::8], input_list[3::8], input_list[4::8], input_list[5::8], input_list[6::8], input_list[7::8]):
             column_space = '{:<%s}{:<%s}{:<%s}{:<%s}{:<%s}{:<%s}{:<%s}{:<}' % (longest_length, longest_length, longest_length, longest_length, longest_length, longest_length, longest_length )
             output = column_space.format(a,b,c,d,e,f,g,h)
             print(output)
    elif terminal_space_seventh >= longest_length and list_size >= 7:
        for a,b,c,d,e,f,g in zip(input_list[::7],input_list[1::7],input_list[2::7], input_list[3::7], input_list[4::7], input_list[5::7], input_list[6::7]):
             column_space = '{:<%s}{:<%s}{:<%s}{:<%s}{:<%s}{:<%s}{:<}' % (longest_length, longest_length, longest_length, longest_length, longest_length, longest_length)
             output = column_space.format(a,b,c,d,e,f,g)
             print(output)
    elif terminal_space_sixth >= longest_length and list_size >= 6:
         for a,b,c,d,e,f in zip(input_list[::6],input_list[1::6],input_list[2::6], input_list[3::6], input_list[4::6], input_list[5::6]):
             column_space = '{:<%s}{:<%s}{:<%s}{:<%s}{:<%s}{:<}' % (longest_length, longest_length, longest_length, longest_length, longest_length)
             output = column_space.format(a,b,c,d,e,f)
             print(output)
    elif terminal_space_fifth >= longest_length and list_size >= 5:
        for a,b,c,d,e in zip(input_list[::5],input_list[1::5],input_list[2::5], input_list[3::5], input_list[4::5]):
            column_space = '{:<%s}{:<%s}{:<%s}{:<%s}{:<}' % (longest_length, longest_length, longest_length, longest_length)
            output = column_space.format(a,b,c,d,e)
            print(output)
    elif terminal_space_quarter >= longest_length and list_size >= 4:
        for a,b,c,d in zip(input_list[::4],input_list[1::4],input_list[2::4], input_list[3::4]):
            column_space = '{:<%s}{:<%s}{:<%s}{:<}' % (longest_length, longest_length, longest_length)
            output = column_space.format(a,b,c,d)
            print(output)
    elif terminal_space_third >= longest_length and list_size >= 3:
        for a,b,c in zip(input_list[::3],input_list[1::3],input_list[2::3]):
            column_space = '{:<%s}{:<%s}{:<}' % (longest_length, longest_length)
            output = column_space.format(a,b,c)
            print(output)
    elif terminal_space_half >= longest_length and list_size >= 2:
        for a,b in zip(input_list[::2],input_list[1::2]):
            column_space = '{:<%s}{:<}' % longest_length
            output = column_space.format(a,b)
            print(output)

作为解释,这做了一些不同的事情。

首先,它使用os.popen获取当前用户终端的列数。

第二,它占用列数并分成两半,增加到第八位。这将用于比较列表中最长的字符串,以确定最适合此的列数。

第三是使用内置的python函数max()拉出的列表中最长的字符串。

第四位,将获取最长的字符串的长度,然后在其中添加一个以进行填充。列表的长度也要考虑在内,因此如果列表少于8个项目,它将仅列出存在的项目数。

第五,将最长的字符串长度与从一列到八列的每个终端空间进行比较。如果列大于或等于长度,则可以使用它。例如,最长的字符串是10,除以八的列(terminal_space_eighth)为8,但除以七的列(terminal_space_seventh)为12,则将有七个列。将有七个,因为最长的字符串可以容纳12个字符,但不能容纳8个字符。

还值得注意的是考虑到列表的长度,以防止创建比列表项更多的列。

第六是@Aman的解释的扩展: https://stackoverflow.com/a/1524132/11002603

索引 就本例而言,让我代表由终端尺寸确定的数字。 input_list[::i]这将选择i处的元素。在前面添加一个数字,例如input_list[1::i]会偏移起点(请记住python认为0是有效数字,这就是为什么最初不使用它的原因。)

压缩

Zip用于创建具有列表元素的元组。例如,输出列表将类似于以下内容

zip([string1,string2,string3], [string4,string5, string6], [string7,string8,string9])
output : [(string1,string4,string7), (string2,string5, string8), (string3,string6,string9)]

一起使用 根据列数,字母仅用于表示拆分。因此,例如,如果终端中仅容纳5列,则将使用以下内容

for a,b,c,d,e in zip(input_list[::5],input_list[1::5],input_list[2::5], input_list[3::5], input_list[4::5]):

这将采用从zip和存储创建的元组,然后将其作为a,b,c,d和e变量,以便我们可以在循环中调用它们。

然后,使用列空间将a,b,c,d和e中的每一个格式化为相应的列,并在其中确定每列的长度。该长度基于上面确定的字符串长度。

答案 17 :(得分:0)

已经有很多答案,但是我将分享我的解决方案,该解决方案除了将列表打印成多列外,还从终端宽度和列表中最长的字符串中动态选择列数。 / p>

import os
cols = os.popen('stty size', 'r').read().split()[1]

def print_multicol(my_list):
    max_len = len(max(my_list,key=len)) + 2
    ncols = (int(cols) -4 ) / max_len
    while my_list:
        n = 0
        while n < ncols:
            if len(my_list) > 0 :
                fstring = "{:<"+str(max_len)+"}"
                print fstring.format(my_list.pop(0)),
            n += 1
        print

a_list = "a ab abc abcd abcde b bc bcde bcdef c cde cdef cdfg d de defg"
a_list += "defgh e ef efg efghi efghij f fg fgh fghij fghijk"

print_multicol(a_list.split())

答案 18 :(得分:0)

[print('{:20}'.format(key), end='\t') if (idx + 1) % 5 else print(key, end='\n') for idx, key in enumerate(list_variable)]

for idx, key in enumerate(list_variable):
    if (idx + 1) % 5:
        print('{:20}'.format(key), end='\t')
    else:
        print(key, end='\n')

答案 19 :(得分:0)

允许不均匀的列非常有用,而无需事先知道可以容纳多少列:

>>> words = [string.ascii_lowercase] + list(string.ascii_lowercase)
>>> print format_list(words)
abcdefghijklmnopqrstuvwxyz  b  d  f  h  j  l  n  p  r  t  v  x  z
a                           c  e  g  i  k  m  o  q  s  u  w  y

对于你的例子:

>>> foolist = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi',
... 'netcdf', 'pdcurses-devel', 'msvcrt', 'gdal-grass', 'iconv',
... 'qgis-devel', 'qgis1.1', 'php_mapscript']
>>> print format_list(foolist, spacing=4, width=31)
exiv2-devel       msvcrt
mingw-libs        gdal-grass
tcltk-demos       iconv
fcgi              qgis-devel
netcdf            qgis1.1
pdcurses-devel    php_mapscript

这是代码。请注意,它还处理带有ANSI颜色代码的单词(例如来自colorama包) - 它们不会弄乱列宽。

ansi_pattern = re.compile(r'\x1b\[\d{1,2}m')


def get_nchars(string):
    """Return number of characters, omitting ANSI codes."""
    return len(ansi_pattern.sub('', string))


def format_list(items, indent=0, spacing=2, width=79):
    """Return string listing items along columns.

    items : sequence
        List of items to display that must be directly convertible into
        unicode strings. ANSI color codes may be present, and are taken
        into account in determining column widths
    indent : int
        Number of spaces in left margin.
    spacing : int
        Number of spaces between columns.
    width : int
        Maximum number of characters per line, including indentation.
    """
    if not items:
        return u''
    # Ensure all items are strings
    items = [unicode(item) for item in items]
    # Estimate number of columns based on shortest and longest items
    minlen = min(get_nchars(item) for item in items)
    maxlen = max(get_nchars(item) for item in items)
    # Assume one column with longest width, remaining with shortest.
    # Use negative numbers for ceiling division.
    ncols = 1 - (-(width - indent - maxlen) // (spacing + min(1, minlen)))
    ncols = max(1, min(len(items), ncols))

    # Reduce number of columns until items fit (or only one column)
    while ncols >= 1:
        # Determine number of rows by ceiling division
        nrows = -(-len(items) // ncols)
        # Readjust to avoid empty last column
        ncols = -(-len(items) // nrows)
        # Split items into columns, and test width
        columns = [items[i*nrows:(i+1)*nrows] for i in range(ncols)]
        totalwidth = indent - spacing + sum(
            spacing + max(get_nchars(item) for item in column)
            for column in columns
            )
        # Stop if columns fit. Otherwise, reduce number of columns and
        # try again.
        if totalwidth <= width:
            break
        else:
            ncols -= 1

    # Pad all items to column width
    for i, column in enumerate(columns):
        colwidth = max(get_nchars(item) for item in column)
        columns[i] = [
            item + ' ' * (colwidth - get_nchars(item))
            for item in column
            ]

    # Transpose into rows, and return joined rows
    rows = list(itertools.izip_longest(*columns, fillvalue=''))
    return '\n'.join(
        ' ' * indent + (u' ' * spacing).join(row).rstrip()
        for row in rows
        )

答案 20 :(得分:0)

这是python 3.4中的一个解决方案,它可以自动检测终端宽度并将其考虑在内。在Linux和Mac上测试。

def column_print(list_to_print, column_width=40):
    import os
    term_height, term_width = os.popen('stty size', 'r').read().split()
    total_columns = int(term_width) // column_width
    total_rows = len(list_to_print) // total_columns
    # ceil
    total_rows = total_rows + 1 if len(list_to_print) % total_columns != 0 else total_rows

    format_string = "".join(["{%d:<%ds}" % (c, column_width) \
            for c in range(total_columns)])
    for row in range(total_rows):
        column_items = []
        for column in range(total_columns):
            # top-down order
            list_index = row + column*total_rows
            # left-right order
            #list_index = row*total_columns + column
            if list_index < len(list_to_print):
                column_items.append(list_to_print[list_index])
            else:
                column_items.append("")
        print(format_string.format(*column_items))

答案 21 :(得分:0)

发现这个问题几乎完成了同样的任务。并且我创建了以列数作为参数在多列中打印列表的功能。也许不像单线解决方案那么优雅,但它可能对某人有用。

但是,它处理不完整的列表,例如:它可以打印3行中的11个列表。

分割功能以提高可读性:

def is_printable(my_list):
    return len(my_list) > 0

def create_empty_list(columns):
    result = []
    for num in range(0, columns):
        result.append([])
    return result

def fill_empty_list(empty_list, my_list, columns):
    column_depth = len(my_list) / columns if len(my_list) % columns == 0 else len(my_list) / columns + 1
    item_index = 0
    for column in range(0, columns):
        while len(empty_list[column]) < column_depth:
            if item_index < len(my_list):
                empty_list[column].append(my_list[item_index])
            else:
                empty_list[column].append(" ")  # last column could be incomplete, fill it with space
            item_index += 1

def print_list_in_columns(my_list, columns=1):
    if not is_printable(my_list):
        print 'Nothing to print, sorry...'
        return
    column_width = 25  #(in symbols) Also can be calculated automatically  
    list_to_print = create_empty_list(columns)
    fill_empty_list(list_to_print, my_list, columns)
    iterators = ["it" + str(i) for i in range(0, columns)]
    for iterators in zip(*list_to_print):
        print ("".join(str.ljust(i, column_width) for i in iterators))

和通话部分:

foolist = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf', 
    'pdcurses-devel',     'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel', 
    'qgis1.1', 'php_mapscript']

print_list_in_columns(foolist, 2)

答案 22 :(得分:-1)

from itertools import izip_longest, islice
L = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf', 
    'pdcurses-devel',     'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel', 
    'qgis1.1', 'php_mapscript']

def columnize(sequence, columns=2):
    size, remainder = divmod(len(sequence), columns)
    if remainder: 
        size += 1
    slices = [islice(sequence, pos, pos + size) 
              for pos in xrange(0, len(sequence), size)]
    return izip_longest(fillvalue='', *slices)

for values in columnize(L):
    print ' '.join(value.ljust(20) for value in values)