2013-09-26 108 views
0

好的,我是Python新手,正在學習元組和列表。我一直要求創建一個程序,但是這涉及到將下面的列表:將列表轉換成元組有3個元素的列表?

li = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18] 

中,看起來像這樣的列表:

li = [[(1,2,3),(4,5,6)],[(7,8,9),(10,11,12)],[(13,14,15),(16,17,18)] 

基本上,從一個簡單的列表,包含列表一個包含兩個包含3個元素的元組的子列表。

我感謝您的幫助。

謝謝。

+0

@jozefg:我嘗試使用循環幾種方式,但他們並沒有真正work..I我還是新來的整個事情,所以我真的不知道,很多方法.. – user2390548

+0

我明白,但是stackoverflow往往會更好地幫助修復代碼,而不是爲您編寫代碼。只是爲未來的問題提供建議:)祝你好運 – jozefg

+0

@jozefg:非常感謝。我不知道。這是我在stackoverflow的第一個問題....謝謝你糾正我..乾杯。 – user2390548

回答

1

使用zip()

>>> [zip(*[iter(sub)]*3) for sub in zip(*[iter(li)]*6)] 
[[(1, 2, 3), (4, 5, 6)], [(7, 8, 9), (10, 11, 12)], [(13, 14, 15), (16, 17, 18)]] 
2

最簡單的方法來解決這個是做的兩個步驟:首先,把它分解成3元組的列表。然後,將其分解成2列表的列表。

有兩種方法可以做每一步。


用切片和測距的第一:

>>> li = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18] 
>>> [li[i:i+3] for i in range(0, len(li), 3)] 
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]] 

但我們要3元組,而不是3-名單,所以我們需要添加一個tuple()周圍的表達:

>>> li_3 = [tuple(li[i:i+3]) for i in range(0, len(li), 3)] 

然後,我們再次做同樣的事情:

>>> li_23 = [li_3[i:i+2] for i in range(0, len(li_3), 2)] 

另一種方法是將同一個迭代器壓縮到自己。文檔中的itertools recipes顯示如何執行此操作。實際上,我們只需複製並粘貼配方,然後我們就可以使用它。

>>> from itertools import izip_longest 
>>> def grouper(iterable, n, fillvalue=None): 
... "Collect data into fixed-length chunks or blocks" 
... # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx 
... args = [iter(iterable)] * n 
... return izip_longest(fillvalue=fillvalue, *args) 

現在:

>>> li = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18] 
>>> grouper(li, 3) 
<itertools.zip_longest at 0x10467dc00> 

它給了我們一個迭代器;我們必須把它變成一個列表,查看元素:

>>> list(grouper(li, 3)) 
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]] 

所以,現在我們只是重複同樣的步驟:

>>> list(grouper(grouper(li, 3), 2)) 
[((1, 2, 3), (4, 5, 6)), ((7, 8, 9), (10, 11, 12)), ((13, 14, 15), (16, 17, 18))] 

除非我們得到的元組的元組,我們希望清單的元組,所以:

>>> li_23 = [list(group) for group in grouper(grouper(li, 3), 2)] 

有應該是一個和唯一一個明顯的方式做事情在Python。那麼,這是什麼?

  • 第一個需要一個列表或其他序列;第二個需要任何迭代。
  • 如果你在最後有剩餘值,第一個給你一個部分組;第二個墊上最後一組。
  • 第二個是非常容易修改放棄不完整的最後一組,而不是填充它,並不難修改給你一個部分組;第一個很難修改。
  • 第一個對新手來說更容易理解,但是一旦你理解了這個概念,讀起來可能會更難。
  • 任何一個都可以很容易地包裝在一個函數中,但第二個已經在食譜(或more_itertools第三方包)中包裝好了。

其中一種差異通常對您的用例很重要,在這種情況下,明顯的做法是按照您的要求進行操作。對於這樣的簡單案例,無論哪一個都不重要...做任何你覺得更具可讀性的案例。

0

鑑於

li = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18] 

您可以將與zip(*[iter(li)]*3)項目:

zip(*[iter(li)]*3) 
#>>> <zip object at 0x7f0a5578ca28> 

並檢查:

list(zip(*[iter(li)]*3)) 
#>>> [(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12), (13, 14, 15), (16, 17, 18)] 

然後你就可以在zip(*[iter(li)]*3)zip(*[...]*2)

zip(*[zip(*[iter(li)]*3)]*2) 
#>>> <zip object at 0x7f0a5578c998> 

並檢查:

list(zip(*[zip(*[iter(li)]*3)]*2)) 
#>>> [((1, 2, 3), (4, 5, 6)), ((7, 8, 9), (10, 11, 12)), ((13, 14, 15), (16, 17, 18))] 

內項目不是一個列表,因此map它一個:

map(list, zip(*[zip(*[iter(li)]*3)]*2)) 
#>>> <map object at 0x7f0a5afd80d0> 

並檢查:

list(map(list, zip(*[zip(*[iter(li)]*3)]*2))) 
#>>> [[(1, 2, 3), (4, 5, 6)], [(7, 8, 9), (10, 11, 12)], [(13, 14, 15), (16, 17, 18)]] 
+1

可讀性值! – hexparrot

+0

當然,當然。但在期待好的答案之前試圖給出一個好問題也是如此)。當分成3行時,這實際上非常易讀。 – Veedrac

+0

啊我喜歡和下一個人一樣的單線球員,但是和乘法一起擴展的並排論點......! – hexparrot

2

我個人很喜歡這種方法:

>>> li = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18] 
>>> 
>>> v = iter(li) 
>>> li = [(i, next(v), next(v)) for i in v] # creates list of tuples 
>>> 
>>> v = iter(li) 
>>> li = [[i, next(v)] for i in v] # creates list of lists of tuples 
>>> 
>>> li 
[[(1, 2, 3), (4, 5, 6)], [(7, 8, 9), (10, 11, 12)], [(13, 14, 15), (16, 17, 18)]] 

通過,如果元素沒有在這樣的結構適合,這將產生一個錯誤的方式,例如考慮:

>>> l = [1, 2, 3] 
>>> v = iter(l) 
>>> 
>>> [(i, next(v)) for i in v] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 

這可能會或可能不適合。

如果不是,則簡單的解決方法是給next()第二個參數:

>>> l = [1, 2, 3] 
>>> v = iter(l) 
>>> 
>>> [(i, next(v, None)) for i in v] 
[(1, 2), (3, None)] 

參考: