Python:如何将“扁平”序列转换为元组序列?

时间:2011-03-09 04:39:25

标签: python list forms tuples

例如,我需要从一维坐标列表中创建一个2元组的列表 [1, 2, 1, 5] 需要成为[(1, 2), (1, 5)]。碰巧我已经在Activestate找到了最快,最通用的方法,但是那里列出的代码对相对的Python新手来说是不透明的:

def group3(lst, n):
    return itertools.izip(*[itertools.islice(lst, i, None, n) for i in range(n)])

有人能用英语解释这段代码的用途吗?在这种情况下星号是做什么的?谢谢。

2 个答案:

答案 0 :(得分:2)

itertools.islice函数可以从任何迭代中生成切片。声明:

itertools.islice(lst, 0, None, 2)

简化表示“返回一个迭代器,当评估时,它将返回lst中的每个其他元素,从元素0开始”。 0 arg是起始点,2是步长值(跳过多少来获取下一个值)

最好使用6个元素的列表来说明,因为查看[(1, 2), (1, 5)]可能不清楚哪个函数产生内部元组(它们在最终的izip之前不会生成)。

>>> lst = [1, 2, 3, 4, 5, 6]
>>> list(itertools.islice(lst, 0, None, 2))
[1, 3, 5]
>>> list(itertools.islice(lst, 0, None, 2))
[2, 4, 6]

小心使用发电机;第一个调用将遍历整个序列,耗尽生成器:

>>> def foo():
...     for i in range(6):
...         yield i + 1
>>>
>>> gen = foo()
>>> list(itertools.islice(gen, 0, None, 2)
[1, 3, 5]
>>> list(itertools.islice(gen, 1, None, 2)
[]

你的功能需要产生2个序列,赔率和均衡。这就是列表理解的用武之地:

>>> [itertools.islice(lst, i, None, 2) for i in range(2)]
[<itertools.islice object at 0x7f958a79eaf8>, <itertools.islice object at 0x7f958a79eaa0>]

现在你有两个islice对象准备交错。为此,我们可以使用zip,但itertools.izip更有效,因为它返回一个迭代器:

>>> list(zip([1, 3, 5], [2, 4, 6]))
[(1, 2), (3, 4), (5, 6)]
>>> tmp = itertools.izip(*[itertools.islice(lst, i, None, 2) for i in range(2)])
>>> tmp
<itertools.izip object at 0x7f958a7b6cf8>
>>> list(tmp)
[(1, 2), (3, 4), (5, 6)]

希望有助于澄清步骤。

答案 1 :(得分:1)

这是2元组的替代版本(不像活动状态配方那样通用):

>>> x = [1,2,3,4,5,6,7,8]
>>> [ (x.pop(0), x.pop(0)) for item in range(len(x)/2) ]
[(1, 2), (3, 4), (5, 6), (7, 8)]

这会通过从列表中弹出前两个数字形成一个两元组的列表,直到不再有对为止。