在Python中解压缩给定数量的项目?

时间:2015-04-07 15:22:31

标签: python iterable-unpacking

有没有办法使用'splat'运算符(例如a, *rest = somelist)以消耗一定数量的项目?

使用案例:我想将一些输入分成一个数字,一个列表列表,另一个数字和另一个列表列表。

我的输入如下:

5
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
5
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

我希望名称为first_numfirst_arrangementsecond_numsecond_arrangement,以便:

first_num == 5
first_arrangement == [[1, 2, 3, 4], [5, 6, 7, 8], ...]

等等。

要做到这一点,能够从我已经产生线的迭代中消耗一定数量的项是有用的。像这样的东西作为中间步骤是理想的: first_num, *[4]first_arrangement, second_num, *[4]second_arrangement = lines

正常/规范/ Pythonic解决这个问题的方法是什么?

2 个答案:

答案 0 :(得分:2)

我认为这样做的规范,pythonic方法是将责任放在你正在迭代的生成器上。我定义了一个生成器函数,如下所示:

import itertools

def generate_arrangements(iterable, size=4):
    iterator = iter(iterable)
    while True:
        yield next(iterator)
        yield list(list(row) for row in itertools.islice(iterator, size))

假设您将数据放在如下列表中:

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

然后写:

first_num, first_arr, second_num, second_arr = generate_arrangements(data)

为您提供所需的输出:

>>> first_num
5
>>> first_arr
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]

你也可以同时产生数量和排列,并让用户做一些额外的解包,这可能是一种更自然的方法:

import itertools

def generate_arrangements(iterable):
    iterator = iter(iterable)
    while True:
        number =  next(iterator)
        arrangement = list(list(row) for row in itertools.islice(iterator, 4))
        yield number, arrangement

(first_num, first_arr), (second_num, second_arr) = generate_arrangements(data)

正如@JoranBeasley在评论中所写,这个表单可以很容易地在for循环中使用元组解包,如下所示:

for num,arr in generate_arrangements(data):
    print(num) 
    print(arr)

答案 1 :(得分:1)

目前尚不清楚您接收数据的格式。这些字符串,数据在文件中等。假设data是您的示例输入的StringIO对象。 您可以在迭代器上使用itertools.islice来提取n个项目,例如:

>>> from itertools import islice
>>> d = iter(data)
>>> first_num = int(next(d))
>>> first_arrangement = [[int(x) for x in l.split()] for l in islice(d, 4)]
>>> print(first_num, first_arrangement)
5  [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]