Подтвердить что ты не робот

Как распечатать список более красиво?

Это похоже на Как распечатать список в Python "красиво" , но я хотел бы распечатать список еще красивее - без скобок и апострофов и запятые, и даже лучше в столбцах.

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 

спасибо!

4b9b3361

Ответ 1

Простой:

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

Этот ответ использует тот же метод в ответе @Aaron Digulla, с немного большим количеством пифонического синтаксиса. Это может облегчить понимание некоторых из вышеперечисленных ответов.

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

молния

Списки Zipping (или другие итерации) генерируют кортежи элементов списков. Например:

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]

Ответ 3

Вдохновленный гимелем, выше.

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  

Ответ 4

См. 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)

Ответ 5

То, как это сделал Аарон, может работать с более чем двумя колонами


>>> l = ['exiv2-devel', 'mingw-libs', 'tcltk-demos', 'fcgi', 'netcdf', 
...     'pdcurses-devel',     'msvcrt', 'gdal-grass', 'iconv', 'qgis-devel', 
...     'qgis1.1', 'php_mapscript']
>>> cols = 4
>>> split=[l[i:i+len(l)/cols] for i in range(0,len(l),len(l)/cols)]
>>> for row in zip(*split):
...  print "".join(str.ljust(i,20) for i in row)
... 
exiv2-devel         fcgi                msvcrt              qgis-devel          
mingw-libs          netcdf              gdal-grass          qgis1.1             
tcltk-demos         pdcurses-devel      iconv               php_mapscript       

Ответ 6

Если данные находятся в том формате, который вы предоставили, это немного больше работы


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

Ответ 7

Вот мое решение. (Копировать в 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

Я расширяю решение столбца 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

Нашел этот вопрос, поскольку встретил почти ту же задачу. И я создал функцию для печати списка в нескольких столбцах с числом столбцов в качестве параметра. Возможно, это не так элегантно, как однострочные решения, но это может быть полезно для кого-то.

Однако он обрабатывает неполные списки, например: он может печатать список из 11 в 3 строках.

Функция расщеплена для лучшей читаемости:

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)

Ответ 10

Здесь находится решение в 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))

Ответ 11

Полезно разрешать неравномерные столбцы, не задумываясь заранее, сколько столбцов вы можете поместить:

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

Ответ 12

Как насчет чего-то подобного?

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

Ответ 13

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

Ответ 14

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)