How to print a list more nicely?

前端 未结 22 1274
北荒
北荒 2020-12-01 09:34

This is similar to How to print a list in Python “nicely”, but I would like to print the list even more nicely -- without the brackets and apostrophes and commas, and even b

22条回答
  •  死守一世寂寞
    2020-12-01 10:05

    It's useful to allow for uneven columns, without having to know in advance how many columns you can fit:

    >>> 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
    

    For your example:

    >>> 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
    

    Here is the code. Note that it also handles words with ANSI color codes (such as from the colorama package) - they won't mess up the column widths.

    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
            )
    

提交回复
热议问题