Как распечатать список более красиво?
Это похоже на Как распечатать список в 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
спасибо!
Ответы
Ответ 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)