Python already has an itertools.accumulate
function. However, this function accumulates from left to right:
>>> list(itertools.accumulate([[x] for x in range(5)]))
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4]]
Instead of that, I would like to accumulate from right to left, like so:
>>> list(accumulate_from_right([[x] for x in range(5)]))
[[0, 1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4], [3, 4], [4]]
My current solution (which is only applicable to lists) is very inefficient and ugly:
>>> list(x[::-1] for x in accumulate([y] for y in reversed(range(5))))[::-1]
[[0, 1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4], [3, 4], [4]]
What is the best way to accumulate a list from right to left?
Edit: I'm using a range just as an example. I would like to be able to apply this method with any nested list.
Here's another example that doesn't use range:
>>> list(accumulate_from_right(['a', 'b', 'c']))
['abc', 'bc', 'c']
You only need to make a single pass over the input of accumulate_from_right
:
def accumulate_from_right(vals):
return [vals[i:] for i in range(len(vals))]
print(accumulate_from_right(list(range(5))))
print(accumulate_from_right(['a', 'b', 'c']))
Output:
[[0, 1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4], [3, 4], [4]]
[['a', 'b', 'c'], ['b', 'c'], ['c']]