我有一个for循环来创建列表,可以改为使用列表理解吗? [英] I have a for loop to create a list, can I use a list comprehension instead?
问题描述
让我们有一个值列表和一个任意整数.
Let's have a list of values and an arbitrary integer number.
values = ['5', '3', '.', '.', '7', '.', '.', '.', '.', '6', '.', '.', '1', '9', '5', '.', '.', '.', '.', '9', '8', '.', '.', '.', '.', '6', '.', '8', '.', '.', '.', '6', '.', '.', '.', '3', '4', '.', '.', '8', '.', '3', '.', '.', '1', '7', '.', '.', '.', '2', '.', '.', '.', '6', '.', '6', '.', '.', '.', '.', '2', '8', '.', '.', '.', '.', '4', '1', '9', '.', '.', '5', '.', '.', '.', '.', '8', '.', '.', '7', '9']
n = 9
我想将值与n
数字连续分组.
I'd like to group the values with n
numbers in a row.
让我们假设n=9
,即连续9个数字.
Let us suppose n=9
, that is 9 numbers will be in a row.
结果应该是这样的:
grouped_values = [
['5', '3', '.', '.', '7', '.', '.', '.', '.'],
['6', '.', '.', '1', '9', '5', '.', '.', '.'],
['.', '9', '8', '.', '.', '.', '.', '6', '.'],
['8', '.', '.', '.', '6', '.', '.', '.', '3'],
['4', '.', '.', '8', '.', '3', '.', '.', '1'],
['7', '.', '.', '.', '2', '.', '.', '.', '6'],
['.', '6', '.', '.', '.', '.', '2', '8', '.'],
['.', '.', '.', '4', '1', '9', '.', '.', '5'],
['.', '.', '.', '.', '8', '.', '.', '7', '9']]
我可以这样:
def group(values, n):
rows_number = int(len(values)/n) # Simplified. Exceptions will be caught.
grouped_values = []
for i in range(0, rows_number):
grouped_values.append(values[i:i+9])
但是有人怀疑可以在这里使用列表理解. 您能帮我了解如何完成吗?
But there is a suspicion that list comprehension can be used here. Could you help me understand how can it be done?
推荐答案
只需将list.append()
调用中的表达式移到最前面,然后添加for
循环:
Just move the expression in the list.append()
call to the front, and add the for
loop:
grouped_values = [values[i:i + 9] for i in range(rows_number)]
请注意,这不会将输入列表切成连续的 元素块.它会产生一个滑动窗口;您先切片values[0:9]
,然后切片values[1:10]
,依此类推.它将在输入数据上生成窗口,每个窗口的长度为9,其中8个元素与前一个窗口重叠.要生成连续的长度为9的块,请使用range(0, len(values), n)
作为范围,而无需计算rows_number
:
Note that this does not slice up your input list into chunks of consecutive elements. It produces a sliding window; you slice values[0:9]
then values[1:10]
, etc. It produces windows onto the input data, each of length 9, with 8 elements overlapping with the previous window. To produce consecutive chunks of length 9, use range(0, len(values), n)
as the range, no need to calculate rows_number
:
grouped_values = [values[i:i + n] for i in range(0, len(values), n)]
只要您看到这样的模式:
Whenever you see a pattern like this:
<list_name> = []
for <targets> in <iterable>:
<list_name>.append(<expression>)
<expression>
不引用<list_name>
的地方,您可以轻松地将其转换为
where <expression>
does not reference <list_name>
, you can trivially turn that into
<list_name> = [<expression> for <targets> in <iterable>]
这里唯一的区别是,只有在执行整个列表理解之后的之后,才设置list_name
.您不能从列表理解中引用正在构建的列表.
The only difference here is that list_name
is not set until after the whole list comprehension has been executed. You can't reference the list being built from inside the list comprehension.
有时候,您需要在循环主体中移动其他代码,以将最终的<expression>
值生成单个表达式,然后再到达上述模式.
Sometimes you need to move additional code in the loop body that produces that final <expression>
value into a single expression before you arrive at the above pattern.
请注意,<expression>
本身产生列表对象并不重要.它们可以是全新的列表推导或任何其他有效的Python表达式.
Note that it doesn't matter here that <expression>
itself produces list objects; they can be entirely new list comprehensions or any other valid Python expression.
如果有更多的for
循环或if
语句具有嵌套级别,则在结果列表理解中从左到右列出那些添加的for
循环和if
语句;例如模式
When there are more for
loops or if
statements with added nested levels, then list those added for
loops and if
statements from left-to-right in the resulting list comprehension; for example, the pattern
<list_name> = []
for <targets1> in <iterable1>:
if <test_expression>:
for <targets2> in <iterable2>:
<list_name>.append(<expression>)
成为
<list_name> = [
<expression>
for <targets> in <iterable>
if <test_expression>
for <targets2> in <iterable2>
]
这篇关于我有一个for循环来创建列表,可以改为使用列表理解吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!