«Что-то вроде функции CDR в Lisp» тривиально:
acc[1:]
Это будет значительно быстрее, чем ваша попытка, но только с постоянным коэффициентом.
Впрочем, делать это не имеет особого смысла. Весь смысл CDR состоит в том, что когда ваши списки являются связанными списками, хранящимися в ячейках CONS, переход от одной ячейки к ее хвосту является одной операцией на машинном языке. Но с массивами (что и есть списки Python), acc[1:]
- или более сложная вещь, которую вы пытались написать, или фактически любая возможная реализация - выделяет целый новый массив размера N-1 и копирует значения N-1 .
Эффективность затрат на выполнение этого снова и снова (в алгоритме, который ожидал, что он будет почти бесплатным) будет настолько велика, что ускорение с постоянным коэффициентом использования acc[1:]
вряд ли будет достаточно улучшение, чтобы сделать его приемлемым.
Большинство алгоритмов, которые работают быстро с CDR, будут медленными с этим типом нарезки, а большинство алгоритмов, которые работают быстро с этим типом срезов, будут медленными с CDR. Вот почему у нас есть несколько структур данных, во-первых, потому что они хороши для разных вещей.
Если вы хотите узнать наиболее эффективный способ сворачивания / уменьшения массива - это способ, которым functools.reduce
(и варианты его, предлагаемые такими библиотеками, как toolz
), это просто: итерация.
И просто повторение имеет еще одно огромное преимущество. Python не просто имеет списки, он имеет абстракцию, называемую итерациями, которая включает итераторы и другие типы, которые могут лениво генерировать свое содержимое. Если вы складываетесь вперед, вы можете воспользоваться этой ленью. (Свертывание в обратном направлении, конечно, занимает линейное пространство, либо явно, либо в стеке, но это все же лучше, чем квадратичное копирование.) Игнорирование этого факта отрицательно сказывается на цели.