How to print a list more nicely?

前端 未结 22 1277
北荒
北荒 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:08

    If the data is in the format you have provided, it is a little more work

    
    >>> 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
    
    0 讨论(0)
  • 2020-12-01 10:08

    Here's my solution. (Copy in GitHub gist)

    It takes terminal width as input and displays only as many columns that can be fit in it.

    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))
    
    0 讨论(0)
  • I extend an n column solution to @Aman's answer

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

    Testing

    Set up the test with random string lengths

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

    which returns

    ## -- 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
    
    0 讨论(0)
  • 2020-12-01 10:10
    [print('{:20}'.format(key), end='\t') if (idx + 1) % 5 else print(key, end='\n') for idx, key in enumerate(list_variable)]
    

    or

    for idx, key in enumerate(list_variable):
        if (idx + 1) % 5:
            print('{:20}'.format(key), end='\t')
        else:
            print(key, end='\n')
    
    0 讨论(0)
  • 2020-12-01 10:14

    As an expansion of @Aman below is a function which takes a list of strings and outputs them in columns based on the terminal size.

    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)
    

    As an explanation this does a few different things.

    First it gets the number of columns for the current user's terminal using os.popen.

    Second it takes the number of columns and divides in half, increasing to eighth. This will be used to compare the longest string in the list to determine the number of columns best suited for this.

    Third is the longest string of the list pulled using the build in python function max().

    Forth the length of the longest string is taken and then has one added to it for padding. The length of the list is taken as well so that if the list is less than 8 items it will only list the number of items that exist.

    Fifth the longest string length is compared to each of the terminal spaces from one column to eight. If the column is greater than or equal to the length then it can be used. For example is the longest string is 10 and the columns divided by eight(terminal_space_eighth) is 8 but columns divided by seven(terminal_space_seventh) is 12, there will be seven columns. There will be seven because the longest string can fit in 12 characters but not in 8 characters.

    It's also worth noting the length of the list is taken into consideration to prevent creating more columns than list items.

    Sixth is an expansion of the explanation by @Aman : https://stackoverflow.com/a/1524132/11002603

    Indexing Lets let i represent the number determined by terminal size for the sake of this example. input_list[::i] This selects element at i. Adding a number at the front such as input_list[1::i] offsets the starting point(remember python considers 0 a valid number which is why it's not used initially.)

    Zipping

    Zip is used to create a tuple with elements of a list. For example The output list will look similar to below

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

    Using together Depending on the number of columns, the letters are just used to represent a split. So for example if only 5 columns fit in the terminal, the following will be used

    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]):
    

    This will take of the tuples created from zipping and store then as a,b,c,d and e variables so we can call them within the loop.

    The column space is then used for format each of a,b,c,d and e into respective columns and is where the length of each column is determined. The length is based on the string length determined above.

    0 讨论(0)
  • 2020-12-01 10:15

    How about something like this?

    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)
    

    Output

    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
    
    0 讨论(0)
提交回复
热议问题