#python #python-3.x #itertools #accumulate
Вопрос:
В Python уже есть itertools.accumulate
функция. Однако эта функция накапливается слева направо:
>>> list(itertools.accumulate([[x] for x in range(5)]))
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4]]
Вместо этого я хотел бы накапливать справа налево, вот так:
>>> 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]]
Мое текущее решение (которое применимо только к спискам) очень неэффективно и уродливо:
>>> 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]]
Как лучше всего накапливать список справа налево?
Редактировать: Я использую диапазон только в качестве примера. Я хотел бы иметь возможность применять этот метод к любому вложенному списку.
Вот еще один пример, в котором не используется диапазон:
>>> list(accumulate_from_right(['a', 'b', 'c']))
['abc', 'bc', 'c']
Комментарии:
1. Это вопрос,
accumulate
в частности, или просто о том, как получить список «нисходящих» суффиксов?2.
print(list(itertools.accumulate([[x] for x in range(5, 0, -1)]))[::-1])
?3. Было бы полезно, если бы вы показали еще несколько примеров, чтобы стало ясно, каким образом вы хотите, чтобы это было обобщено.
4. @chepner Извини! Я неправильно понял, что вы имели в виду под «нисходящими» суффиксами. Я хочу, чтобы функция могла применять этот метод к любому списку!
Ответ №1:
Вам нужно всего лишь сделать один проход по входу 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']))
Выход:
[[0, 1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4], [3, 4], [4]]
[['a', 'b', 'c'], ['b', 'c'], ['c']]
Комментарии:
1. Это довольно умно, но есть ли способ обобщить этот метод? Я использовал диапазон только в качестве примера.
2. @PradhyumR, это должно хорошо обобщать — просто замените свой список на
range(5)
🙂3. Метод @Tim Ajax1234 использует сопоставление шаблонов и диапазон для создания желаемого результата. Это не будет хорошо обобщаться на строки (для чего я это и использую).
Ответ №2:
Вы могли бы попробовать что-то вроде
[list(range(i, 5)) for i in range(5)]
ВОЗВРАТ
[[0, 1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4], [3, 4], [4]]
Ответ №3:
Разве не легко использовать itertools, чтобы накапливать и использовать [::-1] в результате для обратного?
list(itertools.accumulate([[x] for x in range(5)]))[::-1]
Комментарии:
1. Нет, фактическое содержание списка будет другим