Лисп, итерация назад - PullRequest
       15

Лисп, итерация назад

0 голосов
/ 24 октября 2018

Есть ли способ (с циклом или итерацией, не имеет значения) перебирать последовательность в обратном порядке?

Кроме (loop for i downfrom 10 to 1 by 1 do (print i)), который работает с индексами и требует длины, или (loop for elt in (reverse seq)), который требует обратной последовательности (даже хуже, чем первый вариант).

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Итерация может сделать это :

(iterate (for x :in-sequence #(1 2 3) :downto 0)
         (princ x))
; => 321

Как уже отмечали другие, это будет очень неэффективно, если используется в списках.

0 голосов
/ 24 октября 2018

Для списков самым простым является (dolist (x (reverse list)) ..) или использование более эффективного nreverse, если список можно изменить.

Для векторов альтернатива - dotimes с вычислением индекса, что-то вроде:

(let* ((vec #(1 2 3))
       (len (length vec)))
   (dotimes (i len)
      (print (aref vec (- len i 1)))))

Обычно списки повторяются с самого начала, так как каждый минус указывает на следующий.Делать это сзади неэффективно.

Если у вас, тем не менее, есть список, и вы хотите быстрый обратный или произвольный доступ, можно принудительно привести его к вектору, используя, например, (coerce my-list 'array), а затем получить доступ к элементам, используя aref (или приведите к simple-vector и используйте svref).

Если вы один из тех, кто строит список, подумайте о создании настраиваемого вектора с заполнением-указателем (см. Документацию make-array) и затем используйтеvector-push-extend для добавления предметов.Это дает быстрый произвольный доступ с самого начала.

...