When writing code, most sane people like to keep their code as short as possible, trying to reduce the spaghetiness that is their code. At least, that’s my opinion. (You can keep your code as Italian as you want it to be.)
However, the desire to keep our code to as few lines as possible can go from the simple want of readability to… well… this.
def sumOddLengthSubarrays(self, arr: List[int]) -> int:
return sum(sum(sum(arr[j:j + i]) for j in range(0, len(arr) - i + 1)) for i in range(1, len(arr) + 1, 2))
Beautiful. So, what does the code do? It solves this leetcode problem.
For those who do not want to open the link, the problem is simple: Find the sums of all subarrays of integer array arr
where the length of each sub array is odd.
For example:
Input: arr = [1,4,2,5,3]
Output: 58
Explanation: The odd-length subarrays of arr and their sums are:
[1] = 1
[4] = 4
[2] = 2
[5] = 5
[3] = 3
[1,4,2] = 7
[4,2,5] = 11
[2,5,3] = 10
[1,4,2,5,3] = 15
If we add all these together we get 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58
Makes sense? good. The code can easily be solved in a couple of lines.
We have two iterators: i
and j
. i
iterates over the possible odd lengths in the range [1, len(arr)]
. j
iterates over all the indices in arr
that would allow a subarray of length i
to exist.
A more common solution would look like this:
def sumOddLengthSubarrays(self, arr: List[int]) -> int:
res = 0
for i in range(1, len(arr) + 1, 2): # controls subarray length
for j in range(0, len(arr) - i + 1): # controls subarray position
res += sum(arr[j : j + i])
return res
So, how can we turn this into a singe line?
Comprehensions
We can use the built-in sum()
function to get the sum of all elements in an array, generator, range, or comprehension. For example:
>>> sum(i ** 2 for i in range(10))
285
We can start the line with a sum
function that contains a comprehension:
return sum(j_iter for i in range(1, len(arr) + 1, 2))
The j_iter
part is another sum with a comprehension. Here, for j in range(0, len(arr) — i + 1)
, we add sum(arr[j : j + i])
.
so j_iter
would be replaced with this:
sum(sum(arr[j:j + i]) for j in range(0, len(arr) - i + 1))
The entire line would look like this:
return sum(sum(sum(arr[j:j + i]) for j in range(0, len(arr) - i + 1)) for i in range(1, len(arr) + 1, 2))
Here’s a more visual representation of it:
return sum(
sum(
sum(arr[j:j + i])
for j in range(0, len(arr) - i + 1)) # controls subarray position
for i in range(1, len(arr) + 1, 2)) # controls subarray length
That’s all for now!
>>Avi