2008-10-05 12 views
16

Ich versuche, eine Liste der Zeichenfolgenwerte in einem 2 Spaltenformat auszugeben. Die Standardmethode zum Erstellen einer Liste von Zeichenfolgen in "normal text" ist die string.join Methode. Allerdings benötigt es nur 2 Argumente, so dass ich nur eine einzelne Spalte mit "\ n" erstellen kann. Ich dachte, ich würde versuchen, eine Schleife zu erstellen, die einfach einen Tab zwischen Spalten hinzufügen würde, aber die Logik funktionierte nicht richtig.Formatieren einer Liste von Text in Spalten

Ich fand eine ActiveState page, die eine ziemlich komplizierte Art es zu tun hat, aber es ist vor 4 Jahren. Gibt es einen einfachen Weg, es heutzutage zu tun?


bearbeiten Hier ist die Liste, die ich verwenden möchte.

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

Ich möchte nur die Ausgabe diese Liste in ein einfaches, 2 Spaltenformat Raum zu reduzieren. Idealerweise sollte zwischen den Spalten ein normaler Abstand liegen, aber ich kann damit arbeiten.

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

Können Sie den tatsächlichen Eingabewert und das erwartete Ausgabeformat angeben? Es ist nicht sehr klar, wie Ihre Eingabeliste aussieht. –

Antwort

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

nicht so flexibel wie die Active Lösung, aber kürzer :-)

+0

Dies löst nicht das Problem, nur durch das Einfügen von Tabulatoren werden die Spalten getrennt, wenn der Inhalt unterschiedliche Breiten hat (wie im Beispiel des OPs 'schlechte' Ausgabe) – sidewinderguy

+1

@sidewinderguy aber es ist kurz :-) –

+1

In der Tat es ist unglaublich kurz :) – sidewinderguy

11

zwei Spalten durch Tabulatoren getrennt sind, miteinander verbunden in Zeilen. Suchen Sie in itertools für Iteratoräquivalente, um eine platzsparende Lösung zu erreichen.

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

Hoppla ... wurde von S.Lott erwischt (danke).

Eine allgemeinere Lösung behandelt eine beliebige Anzahl von Spalten und ungeraden Listen. Leicht modifiziert von S.lott, mit Generatoren, um Platz zu sparen.

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

Leider funktioniert das nicht gut für eine ungerade Anzahl von Elementen. –

+0

Der zweite Teil ist großartig! – Richard

3

Es ist langatmig, also werde ich es in zwei Teile zerlegen.

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) 

Es kann natürlich als eine einzige laaaange Aussage gemacht werden.

Dies funktioniert auch für eine ungerade Anzahl von Fähigkeiten.

+0

Wow, das ist perfekt. – Richard

0

Die format_columns Funktion sollte das tun, was Sie wollen:

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 

Dies setzt voraus, dass Sie mit Generatoren zur Verfügung eine Python haben.

3

hier eine Erweiterung der Lösung von gimel vorgesehen ist, die mit gleichem Abstand Spalten zu drucken.

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) 

, die so etwas wie dieses

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 zurück ... ... `

+0

Ich erhalte diese Störung, wenn ich Ihre Methode auf meiner Liste der Saiten versuchen:
'Traceback (jüngste Aufforderung zuletzt): File "tars.py", Zeile 45, in Druck fmtcols (Arbeitsplätze, 3) Datei "tars.py", Zeile 10, in fmtcols maxwidth = max (Karte (Lambda x: len (x), Meineliste)) Datei "tars.py", Zeile 10, in maxwidth = max (Karte (Lambda x: len (x), mylist)) TypeError: Objekt vom Typ 'int' hat keine len() ' – YouHaveaBigEgo

0

Ich denke, viele dieser Lösungen werden zwei conflating getrennte Dinge int o eins.

Sie mögen:

  1. die Lage sein, eine Zeichenfolge zu zwingen, eine bestimmte Breite
  2. Druck zu sein, um einen Tisch

Hier ist ein wirklich einfaches Nehmen auf, wie dies zu tun:

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

Getestet mit Python 2.7.6, funktioniert für mich :) – sidewinderguy

Verwandte Themen