2008-10-05 5 views
16

Próbuję wyświetlić listę wartości ciągu w formacie 2 kolumn. Standardowy sposób tworzenia listy ciągów znaków w "zwykłym tekście" polega na użyciu metody string.join .. Jednak wymaga to tylko 2 argumentów, więc mogę utworzyć tylko jedną kolumnę za pomocą "\ n". Pomyślałem, że próba utworzenia pętli, która po prostu doda tabulację między kolumnami, spowoduje to, ale logika nie działa poprawnie.Formatowanie listy tekstu w kolumny

znalazłem ActiveState page że ma dość skomplikowany sposób to zrobić, ale to od 4 lat temu. Czy jest to obecnie łatwy sposób na zrobienie tego?


Edit Oto lista że chcę używać.

Po prostu chcę wypisać tę listę w prosty, 2-kolumnowy format, aby zmniejszyć miejsce. Idealnie powinna istnieć standardowa przestrzeń między kolumnami, ale mogę z nią pracować.

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

Czy możesz podać faktyczną wartość wejściową i oczekiwany format wyjściowy? Nie jest jasne, jak wygląda twoja lista wejściowa. –

Odpowiedz

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

nie elastyczne w postaci roztworu ActiveState, ale krótszy :-)

+0

To nie rozwiąże problemu, po prostu wstawienie znaków tabulacji spowoduje rozłączenie kolumn, gdy zawartość będzie miała różne szerokości (jak w przykładzie OP 'bad' output) – sidewinderguy

+1

@sidewinderguy, ale jest krótka :-) –

+1

Rzeczywiście jest niesamowicie krótki :) – sidewinderguy

11

dwie kolumny oddzielone karty, połączone w linii. Zajrzyj do itertools dla odpowiedników iteratora, aby uzyskać rozwiązanie efektywne pod względem przestrzeni.

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

Ups ... zostałem schwytany przez S.Lott (dziękuję).

Bardziej ogólne rozwiązanie, obsługuje dowolną liczbę kolumn i list nieparzystych. Lekko zmodyfikowane z S.lott, przy użyciu generatorów, aby zaoszczędzić miejsce.

+0

Niestety, to nie działa dobrze dla nieparzystej liczby elementów. –

+0

Druga część tego jest świetna! – Richard

3

Jest długotrwały, więc podzielę go na dwie części.

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) 

Oczywiście można to zrobić jako pojedyncze oświadczenie.

Działa to również w przypadku nieparzystej liczby umiejętności.

+0

Wow, to jest idealne. – Richard

0

Funkcja format_columns powinien robić to, co chcesz:

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 

ta zakłada, że ​​masz Python z generatorów dostępnych.

3

Oto rozszerzenie rozwiązania dostarczonego przez gimel, która pozwala drukować równo rozstawione kolumny.

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) 

która zwraca coś jak ten

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

otrzymuję ten błąd, gdy próbuję metodę na mojej liście ciągów:
'Traceback (najnowsza połączeń ostatni): Plik„tars.py”, linia 45, w fmtcols drukowania (zadania, 3) Plik "tars.py", wiersz 10, w fmtcols maxwidth = max (mapa (lambda x: len (x), mylist)) Plik "tars.py", wiersz 10, w maxwidth = max (mapa (lambda x: len (x), mylist)) TypeError: obiekt typu "int" nie ma len() ' – YouHaveaBigEgo

0

myślę, że wielu z tych rozwiązań są dwa utożsamiając oddzielne rzeczy int o jeden.

Chcecie:

  1. móc wymusić ciąg być pewną szerokość
  2. druku stół

Oto bardzo prosty zabiorą jak to zrobić:

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') 
+0

Testowany przy użyciu Pythona 2.7.6, działa dla mnie :) – sidewinderguy