2010-07-01 21 views
9

En Lisp, puede tener algo como esto:iterar una cadena de formato sobre una lista

(setf my-stuff '(1 2 "Foo" 34 42 "Ni" 12 14 "Blue")) 
(format t "~{~d ~r ~s~%~}" my-stuff) 

¿Cuál sería la forma más Pythonic para repetir la misma lista? Lo primero que me viene a la mente es:

mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"] 
for x in xrange(0, len(mystuff)-1, 3): 
    print "%d %d %s" % tuple(mystuff[x:x+3]) 

Pero eso me parece incómodo. Estoy seguro de que hay una mejor manera?


Bueno, a menos que alguien más adelante proporciona un mejor ejemplo, creo que la solución de gnibbler es el más bonito \ cercano, aunque puede no ser tan evidentes en un primer momento cómo hace lo que hace:

mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"] 
for x in zip(*[iter(mystuff)]*3): 
    print "{0} {1} {2}".format(*x) 
+1

Como un aparte, ¿no es incómoda una palabra tan terriblemente maravillosa? ¡Simplemente * parece * incómodo! –

+2

Parece incómodo en comparación, pero realmente no es tan malo. – ChaosPandion

+2

+1 porque no tengo idea de si te referías a mi comentario o al código. * Por favor * no aclare, ¡la ambigüedad es mucho más entretenida/interesante! –

Respuesta

11
mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"] 
for x in zip(*[iter(mystuff)]*3): 
    print "%d %d %s"%x 

O usando .format

mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"] 
for x in zip(*[iter(mystuff)]*3): 
    print "{0} {1} {2}".format(*x) 

Si la cadena de formato no está codificado, puede analizarlo para averiguar cómo muchos términos por línea

from string import Formatter 
num_terms = sum(1 for x in Formatter().parse("{0} {1} {2}")) 

Poniendo todo junto da

mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"] 
fmt = "{0} {1} {2}" 
num_terms = sum(1 for x in Formatter().parse(fmt)) 
for x in zip(*[iter(mystuff)]*num_terms): 
    print fmt.format(*x) 
+0

I * realmente * me gusta esta solución, y al principio estaba realmente confundido, pero después de hackear el código que es realmente elegante. –

+0

@Wayne Werner, es bueno que averigüe por qué funciona –

3

Para empezar, me gustaría usar el nuevo formato de cadenas en los métodos 2.6+

print "{0} {1} {2}".format(*mystuff[x:x+3]) 
+0

Me había olvidado de eso. Lo limpia un poco ... –

4

Creo join es la característica más similar en Python:

(format t "~{~D, ~}" foo) 

print(foo.join(", ")) 

Es un poco peor cuando se tienen varios elementos en el interior, como se ve, aunque si tiene una función group-by (que es realmente útil de todos modos!), Creo que se puede hacer que funcione sin demasiados problemas. Algo así como:

mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"] 
print(["%d %d %s" % x for x in group(mystuff, 3)].join("\n")) 
+0

Sí, con la adición de una función de generador especializado, puede hacer que se vea realmente bien. –

+0

Sí, supongo que depende de cuánto quieras engañar. Puedes portar 'FORMAT' a Python y decir' FORMAT (True, '~ {~ d ~ r ~ s ~% ~}' ', my_stuff) ', si estuviste realmente aburrido algún fin de semana. :-) – Ken

+0

¡He estado tentado! Por supuesto, también me gustaría que el '~ r' fuera parte de las libs de Python, también ... Ya hay un módulo en sourceforge: http: // sourceforge.net/projects/pynum2word/ –

2

Yo diría que la mayor parte Pythonic sería hacer la lista más profundo:

mystuff = [(1, 2, "Foo"), (34, 42, "Ni"), (12, 14, "Blue")] 
for triplet in mystuff: 
    print "%d %d %s" % triplet 
+0

que es básicamente lo que crea la solución gnibblers: '[x para x en zip (* [iter (mystuff)] * 3)]' = '[(1, 2, 'foo'), (34, 42, 'ni'), (12, 14, 'azul')] '¿Bastante astuto, neh? –

+0

Lo sé, pero creo que es más Pythonic simplemente tener la lista en esa forma, para empezar. Esa fue la pregunta original, ¿verdad? –

+0

Bueno, era un poco ambiguo, así que arreglé la redacción. Realmente estaba más interesado en la parte de iteración/formateo, consumiendo cierto número de valores de lista por iteración. Pero en términos de todo el "programa", tu solución sería más pitonica –

0

Un forro basa en dos Wright:

mystuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"] 
print '\n'.join("{0},{1},{2}".format(*mystuff[x:x+3]) for x in xrange(0, len(mystuff)-1, 3)) 
1
stuff = [1, 2, "Foo", 34, 42, "Ni", 12, 14, "Blue"] 

it = iter(stuff) 
itn = it.next 

print '\n'.join("%d %d %s" % (el,itn(),itn()) 
       for el in it) 

muy comprensible, creo

Cuestiones relacionadas