2010-07-01 261 views
9

在Lisp中的格式字符串,可以有这样的事情:遍历列表

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

什么是最Python的方式来遍历同样的名单?首先想到的是:

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

但这只是感觉尴尬的我。我确定有更好的方法?


那么,除非后来有人提供了一个更好的例子,我觉得gnibbler的解决方案是最好的\最接近的,虽然它可能不会在第一它是如何做的事情确实是相当的明显:

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

顺便说一句,这样一个非常奇妙的单词不难尴尬吗?它看起来很尴尬! – 2010-07-01 20:48:32

+2

比较看起来很尴尬,但它确实没那么糟糕。 – ChaosPandion 2010-07-01 20:49:56

+2

+1,因为如果你是指我的评论或代码,我不知道。 *请*不要澄清,含糊不清更有趣/有趣! – 2010-07-01 21:06:02

回答

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

或者使用.format

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

如果格式字符串不是硬编码的,你可以分析它制定出每行

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

多少项把它放在一起给出

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

我真的很喜欢这个解决方案,开始时我非常困惑,但是在编写真正优雅的代码之后。 – 2010-07-01 21:20:06

+0

@Wayne Werner,很好的解决它为什么起作用 – 2010-07-01 21:28:52

3

对于初学者来说,我会使用较新的字符串格式化方法在2.6+

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

我忘了那个。清理起来有点... – 2010-07-01 21:02:27

4

我觉得join是Python中最相似的特征:

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

print(foo.join(", ")) 

这是一个有点糟糕,当你有多个项目里面,你看,但如果你有一个group-by功能(这是真的有用呢!),我想你可以把它没有太多的麻烦工作。喜欢的东西:

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

是的,加上一个专门的发生器功能,你可以使它看起来非常好。 – 2010-07-01 21:13:23

+0

是的,我猜这取决于你想要作弊多少。如果你在某个周末感到很无聊,你可以将'FORMAT'移植到Python并且说'FORMAT(True,“〜{〜d〜r〜s〜%〜}”,my_stuff)''。 :-) – Ken 2010-07-01 21:18:34

+0

我一直在试探!当然我也希望'〜r'也是Python库的一部分......在sourceforge上已经有一个模块:http:// sourceforge。net/projects/pynum2word/ – 2010-07-01 21:27:49

2

我想说的最Python化将是使名单更深层次:基于赖特

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

这基本上是gnibblers解决方案创建的:'[x for zip in(* [iter(mystuff)] * 3)]'='[(1,2, 'foo'),(34,42,'ni'),(12,14,'blue')]'很漂亮,漂亮吗? – 2010-07-02 12:28:31

+0

我知道这一点,但我认为只有以这种形式开始的列表才是Pythonic。这是原来的问题,对吧? – 2010-07-02 13:12:46

+0

嗯,我有点模棱两可,所以我修改了措词。我真的对迭代/格式化部分更感兴趣 - 每次迭代消耗一定数量的列表值。但就整个“计划”而言,你的解决方案会更加pythonic – 2010-07-02 14:05:08

0

两个班轮:

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) 

非常理解,我觉得