seleccionar - separar por caracter python
Formatear una lista de texto en columnas (7)
Esto funciona
it = iter(skills_defs)
for i in it:
print(''{:<60}{}''.format(i, next(f)))
Estoy tratando de generar una lista de valores de cadena en un formato de 2 columnas. La forma estándar de hacer una lista de cadenas en "texto normal" es usar el método string.join . Sin embargo, solo se necesitan 2 argumentos, así que solo puedo hacer una sola columna con "/ n". Pensé que intentar hacer un ciclo que simplemente agregara una pestaña entre columnas lo haría, pero la lógica no funcionaba correctamente.
Encontré una página de ActiveState que tiene una forma bastante complicada de hacerlo, pero es de hace 4 años. ¿Hay alguna manera fácil de hacerlo hoy en día?
Editar Aquí está la lista que quiero usar.
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"]
Solo quiero mostrar esta lista en un formato simple de 2 columnas para reducir el espacio. Idealmente, debería haber una cantidad estándar de espacio entre las columnas, pero puedo trabajar con ella.
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
data = [ ("1","2"),("3","4") ]
print "/n".join(map("/t".join,data))
No es tan flexible como la solución ActiveState, pero es más corta :-)
Es largo, así que lo dividiré en dos partes.
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 )
Obviamente, se puede hacer como una sola declaración loooong.
Esto también funciona para un número impar de habilidades.
La función format_columns
debe hacer lo que quieras:
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
Esto supone que tienes un Python con generadores disponibles.
Aquí hay una extensión de la solución proporcionada por gimel, que permite imprimir columnas equiespaciadas.
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)
que devuelve algo como esto
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
... ... `
Creo que muchas de estas soluciones combinan dos cosas separadas en una sola.
Tú quieres:
- ser capaz de forzar una cuerda para que tenga un ancho determinado
- imprime una mesa
Aquí hay una idea muy simple sobre cómo hacer esto:
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'')
Dos columnas, separadas por pestañas, unidas en líneas. Busque en itertools equivalentes de iterador para lograr una solución que ahorre espacio.
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
...
Vaya ... me atrapó S.Lott (gracias).
Una solución más general, maneja cualquier cantidad de columnas y listas impares. Ligeramente modificado de S.lott , usando generadores para ahorrar espacio.
def fmtcols(mylist, cols):
lines = ("/t".join(mylist[i:i+cols]) for i in xrange(0,len(mylist),cols))
return ''/n''.join(lines)