2013-09-26 107 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)] 

参考: