Как распечатать список более красиво? - PullRequest
16 голосов
/ 06 октября 2009

Это похоже на Как напечатать список в 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 

спасибо!

Ответы [ 18 ]

19 голосов
/ 31 июля 2014

В этом ответе используется тот же метод в ответе @ Аарона Дигуллы, с чуть более питоническим синтаксисом. Это может облегчить понимание некоторых из приведенных выше ответов.

>>> 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]
11 голосов
/ 06 октября 2009

Simple:

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+
8 голосов
/ 18 марта 2016

Вдохновленный ответом Гимела, выше .

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  
5 голосов
/ 06 октября 2009

См. форматирование списка текстов в столбцы ,

Общее решение, обрабатывает любое количество столбцов и нечетных списков. Символы табуляции разделяют столбцы, используя выражения генератора для экономии места.

def fmtcols(mylist, cols):
    lines = ("\t".join(mylist[i:i+cols]) for i in xrange(0,len(mylist),cols))
    return '\n'.join(lines)
5 голосов
/ 06 октября 2009

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


>>> 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       
3 голосов
/ 06 октября 2009

Если данные в указанном вами формате, это немного больше работы


>>> 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
1 голос
/ 12 июня 2017

Как насчет этого?

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
1 голос
/ 08 февраля 2017

Я расширяю решение 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
1 голос
/ 16 июня 2015

Вот мое решение. ( Копировать в 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))
0 голосов
/ 17 марта 2019

Вот простой способ. См. Встроенные комментарии для объяснения:

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
            )
        )
    )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...