2016-08-20 3 views
0

Я искал все вокруг, но не нашел простого ответа.Нарезка списка с шагом

Как я могу нарезать список в Common Lisp с заданным step, не прибегая к loop? Кажется странным, что subseq не будет принимать третий параметр, то есть (subseq lst start end step).

Python эквивалент:

lst[start:end:step] 

ответ

4

Там нет ничего подобного в стандартном CL. Для его реализации можно использовать REDUCE или DO. Я бы просто использовать LOOP:

Вспомогательная функция:

(defun %take (it what) 
    (cond ((eq what :all) it) 
     ((eq what :none) nil) 
     ((and (numberp what) (plusp what)) 
     (subseq it 0 what)) 
     ((and (numberp what) (minusp what)) 
     (last it (- what))) 
     ((and (consp what) 
       (= (length what) 1) 
       (numberp (first what))) 
     (nth (first what) it)) 
     ((and (consp what) 
       (= (length what) 2) 
       (numberp (first what))    
       (numberp (second what))) 
     (let ((end (if (minusp (second what)) 
         (+ (length it) (second what)) 
         (second what)))) 
      (subseq it (first what) end))) 
     ((and (consp what) 
       (= (length what) 3) 
       (numberp (first what)) 
       (numberp (second what)) 
       (numberp (third what))) 
     (let ((start (first what)) 
       (end (if (minusp (second what)) 
         (+ (length it) (second what)) 
         (second what))) 
       (by-step (third what))) 
      (loop for e = (subseq it start) then (nthcdr by-step e) 
       for i from start below end by by-step 
       collect (first e)))))) 

TAKE:

(defun take (thing &rest description) 
    "Taking things from lists like in Mathematica 
Description is one or more of: 
    :all | :none | [sign]number | (start [end [step]])" 
    (cond ((null description) nil) 
     ((and (consp description) 
       (= (length description) 1)) 
     (%take thing (first description))) 
     (t (loop for e in (%take thing (first description)) 
       collect (apply #'take e (rest description)))))) 

Пример:

CL-USER 27 > (take '(0 1 2 3 4 5 6 7 8 9 10 11) '(2 7 2)) 
(2 4 6) 

CL-USER 28 > (defun sublist (list start end step) 
       (take list (list start end step))) 
SUBLIST 

CL-USER 29 > (sublist '(0 1 2 3 4 5 6 7 8 9 10 11) 2 7 2) 
(2 4 6) 
Смежные вопросы