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
I'd like to group the values with n
numbers in a row.
Let us suppose n=9
, that is 9 numbers will be in a row.
The result should be like this:
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']]
I can do it like this:
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?
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)]
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>)
where <expression>
does not reference <list_name>
, you can trivially turn that into
<list_name> = [<expression> for <targets> in <iterable>]
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.
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.
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.
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>)
becomes
<list_name> = [
<expression>
for <targets> in <iterable>
if <test_expression>
for <targets2> in <iterable2>
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With