2010-07-01 260 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) 

非常理解,我覺得