有没有办法使用'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_num
,first_arrangement
,second_num
,second_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解决这个问题的方法是什么?
答案 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]]