Обратная итерация в Julia

вчера у меня был случай захотеть повторить коллекцию в обратном порядке. Я нашел reverse функция, но это не возвращает итератор, а фактически создает реверсивную коллекцию.

по-видимому, раньше был Reverse итератор, который был удалены несколько лет назад. Я также могу найти ссылка Для что-то (типа?) называется Order.Reverse, но это не относится к моему вопросу.

в Iterators.jl пакет имеет много интересных шаблонов итераций, но, по-видимому, не обратная итерация.

Я конечно могу использовать , а в некоторых случаях, например reverse(eachindex(c)) который возвращает обратный итератор, но я бы предпочел общий обратный итератор.

есть ли такая вещь?

1 ответов


комментарий Джеффа, когда он удалил обратный итератор три года назад (в вопрос связан) так же актуально и сегодня:

Я очень за удаление этого, так как он просто не работает. В отличие от всего остального в итератор.jl это зависит от индексирования, а не итерации, и даже не работает на всем, что индексируется (например, UTF8String). Я ненавижу иметь такие мины на базе.

на самом базовом уровне, итераторы знают только три вещи: запустить итерацию, получить следующий элемент и проверить, выполнена ли итерация. Чтобы создать итератор, который не выделяет с помощью этих примитивов, вам понадобится алгоритм O(n^2): пройдите через весь итератор, считая по ходу, пока не найдете последний элемент. Тогда пройдите итератор снова, только на этот раз остановившись на предпоследнем элементе. Конечно, он не выделяет, но это будет путь медленнее, чем просто сбор итератора в массив, а затем индексирование назад. И он будет полностью сломан для одноразовых итераторов (например,eachline). Поэтому просто невозможно создать эффективный общий обратный итератор.

отметим, что reverse(eachindex(c)) не работает вообще:

julia> reverse(eachindex(sprand(5,5,.2)))
ERROR: MethodError: no method matching reverse(::CartesianRange{CartesianIndex{2}})

одна альтернатива, которая все равно будет работать со смещенными массивами, -reverse(linearindices(c)).