2008-10-05 4 views
16

Я пытаюсь вывести список строковых значений в формат 2 столбца. Стандартный способ составления списка строк в «обычный текст» - это использовать метод string.join. Однако он принимает только 2 аргумента, поэтому я могу сделать только один столбец, используя «\ n». Я думал, что попытка создать цикл, который просто добавит вкладку между столбцами, сделает это, но логика не работает правильно.Форматирование списка текста в столбцы

Я нашел ActiveState page, который имеет довольно сложный способ сделать это, но это от 4 лет назад. Есть ли простой способ сделать это сейчас?


Редактировать Вот список, который я хочу использовать.

skills_defs = ["ACM:Aircraft Mechanic", "BC:Body Combat", "BIO:Biology", 
    "CBE:Combat Engineer", "CHM:Chemistry", "CMP:Computers", 
    "CRM:Combat Rifeman", "CVE:Civil Engineer", "DIS:Disguise", 
    "ELC:Electronics","EQ:Equestrian", "FO:Forward Observer", 
    "FOR:Forage", "FRG:Forgery", "FRM:Farming", "FSH:Fishing", 
    "GEO:Geology", "GS:Gunsmith", "HW:Heavy Weapons", "IF:Indirect Fire", 
    "INS:Instruction", "INT:Interrogation", "JP:Jet Pilot", "LB:Longbow", 
    "LAP:Light Aircraft Pilot", "LCG:Large Caliber Gun", "LNG:Language", 
    "LP:Lockpick", "MC:Melee Combat", "MCY:Motorcycle", "MEC:Mechanic", 
    "MED:Medical", "MET:Meterology", "MNE:Mining Engineer", 
    "MTL:Metallurgy", "MTN:Mountaineering", "NWH:Nuclear Warhead", 
    "PAR:Parachute", "PST:Pistol", "RCN:Recon", "RWP:Rotary Wing Pilot", 
    "SBH:Small Boat Handling","SCD:Scuba Diving", "SCR:Scrounging", 
    "SWM:Swimming", "TW:Thrown Weapon", "TVD:Tracked Vehicle Driver", 
    "WVD:Wheeled Vehicle Driver"] 

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

ACM:Aircraft Mechanic  BC:Body Combat 
BIO:Biology   CBE:Combat Engineer 
CHM:Chemistry  CMP:Computers 
CRM:Combat Rifeman  CVE:Civil Engineer 
DIS:Disguise   ELC:Electronics 
EQ:Equestrian   FO:Forward Observer 
FOR:Forage   FRG:Forgery 
FRM:Farming    FSH:Fishing 
GEO:Geology    GS:Gunsmith 
HW:Heavy Weapons  IF:Indirect Fire 
INS:Instruction    INT:Interrogation 
JP:Jet Pilot   LB:Longbow 
LAP:Light Aircraft Pilot  LCG:Large Caliber Gun 
LNG:Language   LP:Lockpick 
MC:Melee Combat   MCY:Motorcycle 
MEC:Mechanic   MED:Medical 
MET:Meterology  MNE:Mining Engineer 
MTL:Metallurgy  MTN:Mountaineering 
NWH:Nuclear Warhead  PAR:Parachute 
PST:Pistol   RCN:Recon 
RWP:Rotary Wing Pilot  SBH:Small Boat Handling 
SCD:Scuba Diving  SCR:Scrounging 
SWM:Swimming  TW:Thrown Weapon 
TVD:Tracked Vehicle Driver WVD:Wheeled Vehicle Driver 
+0

Не могли бы вы предоставить фактическое входное значение и ожидаемый формат вывода? Не совсем понятно, как выглядит ваш входной список. – 2008-10-06 00:59:49

ответ

0
data = [ ("1","2"),("3","4") ] 
print "\n".join(map("\t".join,data)) 

не гибкая, как раствор ActiveState, но короче :-)

+0

Это не решит проблему, просто вставив символы табуляции, вызовы будут разделены на столбцы, когда содержимое будет иметь разную ширину (как в примере OP «плохого» вывода) – sidewinderguy 2014-11-19 21:34:24

+1

@sidewinderguy, но это коротко :-) – 2014-11-20 09:19:47

+1

Действительно это ужасно коротко :) – sidewinderguy 2014-11-22 02:09:58

11

два колонн, разделенные вкладками, соединенная в линию. Посмотрите на itertools для эквивалентов итераторов, чтобы получить пространство-эффективное решение.

import string 
def fmtpairs(mylist): 
    pairs = zip(mylist[::2],mylist[1::2]) 
    return '\n'.join('\t'.join(i) for i in pairs) 

print fmtpairs(list(string.ascii_uppercase)) 

A B 
C D 
E F 
G H 
I J 
... 

Упс ... был пойман С.Лоттом (спасибо).

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

def fmtcols(mylist, cols): 
    lines = ("\t".join(mylist[i:i+cols]) for i in xrange(0,len(mylist),cols)) 
    return '\n'.join(lines) 
+0

К сожалению, это не работает для нечетного числа элементов. – 2008-10-06 10:33:00

+0

Вторая часть этого замечательно! – Richard 2012-10-07 12:25:03

3

Это длинный ветер, поэтому я разбиваю его на две части.

def columns(skills_defs, cols=2): 
    pairs = [ "\t".join(skills_defs[i:i+cols]) for i in range(0,len(skills_defs),cols) ] 
    return "\n".join(pairs) 

Это, очевидно, может быть сделано как одно утверждение loooong.

Это также работает с нечетным количеством навыков.

0

format_columns функция должна делать то, что вы хотите:

from __future__ import generators 
try: import itertools 
except ImportError: mymap, myzip= map, zip 
else: mymap, myzip= itertools.imap, itertools.izip 

def format_columns(string_list, columns, separator=" "): 
    "Produce equal-width columns from string_list" 
    sublists= [] 

    # empty_str based on item 0 of string_list 
    try: 
     empty_str= type(string_list[0])() 
    except IndexError: # string_list is empty 
     return 

    # create a sublist for every column 
    for column in xrange(columns): 
      sublists.append(string_list[column::columns]) 

    # find maximum length of a column 
    max_sublist_len= max(mymap(len, sublists)) 

    # make all columns same length 
    for sublist in sublists: 
     if len(sublist) < max_sublist_len: 
      sublist.append(empty_str) 

    # calculate a format string for the output lines 
    format_str= separator.join(
     "%%-%ds" % max(mymap(len, sublist)) 
     for sublist in sublists) 

    for line_items in myzip(*sublists): 
     yield format_str % line_items 

if __name__ == "__main__": 
    skills_defs = ["ACM:Aircraft Mechanic", "BC:Body Combat", "BIO:Biology", 
     "CBE:Combat Engineer", "CHM:Chemistry", "CMP:Computers", 
     "CRM:Combat Rifeman", "CVE:Civil Engineer", "DIS:Disguise", 
     "ELC:Electronics","EQ:Equestrian", "FO:Forward Observer", 
     "FOR:Forage", "FRG:Forgery", "FRM:Farming", "FSH:Fishing", 
     "GEO:Geology", "GS:Gunsmith", "HW:Heavy Weapons", "IF:Indirect Fire", 
     "INS:Instruction", "INT:Interrogation", "JP:Jet Pilot", "LB:Longbow", 
     "LAP:Light Aircraft Pilot", "LCG:Large Caliber Gun", "LNG:Language", 
     "LP:Lockpick", "MC:Melee Combat", "MCY:Motorcycle", "MEC:Mechanic", 
     "MED:Medical", "MET:Meterology", "MNE:Mining Engineer", 
     "MTL:Metallurgy", "MTN:Mountaineering", "NWH:Nuclear Warhead", 
     "PAR:Parachute", "PST:Pistol", "RCN:Recon", "RWP:Rotary Wing Pilot", 
     "SBH:Small Boat Handling","SCD:Scuba Diving", "SCR:Scrounging", 
     "SWM:Swimming", "TW:Thrown Weapon", "TVD:Tracked Vehicle Driver", 
     "WVD:Wheeled Vehicle Driver"] 

    for line in format_columns(skills_defs, 2): 
     print line 

Это предполагает, что у вас есть Python с генераторами доступны.

3

Вот является продолжением решения, представленного Gimel, что позволяет печатать равномерно расположенные колонны.

def fmtcols(mylist, cols): 
    maxwidth = max(map(lambda x: len(x), mylist)) 
    justifyList = map(lambda x: x.ljust(maxwidth), mylist) 
    lines = (' '.join(justifyList[i:i+cols]) 
      for i in xrange(0,len(justifyList),cols)) 
    print "\n".join(lines) 

который возвращает что-то вроде этого

ACM:Aircraft Mechanic BC:Body Combat
BIO:Biology CBE:Combat Engineer
CHM:Chemistry CMP:Computers
CRM:Combat Rifeman CVE:Civil Engineer
DIS:Disguise ELC:Electronics ... ... `

0

Я думаю, что многие из этих решений приравнивая два отдельные вещи int o один.

Вы хотите:

  1. быть в состоянии заставить строку быть определенной шириной
  2. печати стол

Вот очень простой взгляд на том, как это сделать:

import sys 

skills_defs = ["ACM:Aircraft Mechanic", "BC:Body Combat", "BIO:Biology", 
"CBE:Combat Engineer", "CHM:Chemistry", "CMP:Computers", 
"CRM:Combat Rifeman", "CVE:Civil Engineer", "DIS:Disguise", 
"ELC:Electronics","EQ:Equestrian", "FO:Forward Observer", 
"FOR:Forage", "FRG:Forgery", "FRM:Farming", "FSH:Fishing", 
"GEO:Geology", "GS:Gunsmith", "HW:Heavy Weapons", "IF:Indirect Fire", 
"INS:Instruction", "INT:Interrogation", "JP:Jet Pilot", "LB:Longbow", 
"LAP:Light Aircraft Pilot", "LCG:Large Caliber Gun", "LNG:Language", 
"LP:Lockpick", "MC:Melee Combat", "MCY:Motorcycle", "MEC:Mechanic", 
"MED:Medical", "MET:Meterology", "MNE:Mining Engineer", 
"MTL:Metallurgy", "MTN:Mountaineering", "NWH:Nuclear Warhead", 
"PAR:Parachute", "PST:Pistol", "RCN:Recon", "RWP:Rotary Wing Pilot", 
"SBH:Small Boat Handling","SCD:Scuba Diving", "SCR:Scrounging", 
"SWM:Swimming", "TW:Thrown Weapon", "TVD:Tracked Vehicle Driver", 
"WVD:Wheeled Vehicle Driver"] 

# The only thing "colform" does is return a modified version of "txt" that is 
# ensured to be exactly "width" characters long. It truncates or adds spaces 
# on the end as needed. 
def colform(txt, width): 
    if len(txt) > width: 
     txt = txt[:width] 
    elif len(txt) < width: 
     txt = txt + (" " * (width - len(txt))) 
    return txt 

# Now that you have colform you can use it to print out columns any way you wish. 
# Here's one brain-dead way to print in two columns: 
for i in xrange(len(skills_defs)): 
    sys.stdout.write(colform(skills_defs[i], 30)) 
    if i % 2 == 1: 
     sys.stdout.write('\n')