Возврат от al oop при условии - PullRequest
0 голосов
/ 02 мая 2020

У меня есть следующая функция:

(defun chooseBest (TSPs dTSPs)
    (let ((minim (minPos dTSPs 0 0)) (j 0) (best nil)) 
        (loop for i in TSPs
             do (cond ((= j minim) (progn (setf best i) (setq j (+ j 1))))
                      (t (setq j (+ j 1)))))        
        best))

Эта функция получает два списка:

TSPs - список путей, подобных этому:

(((1 3600 2300) (2 3100 3300))
 ((3 4700 5750) (22 6650 2300) (23 5400 1600)))

и список расстояний, связанных с ними:

(distancePath1 distancePath2)

Функция minPos возвращает позицию списка с меньшим номером, которая является путем с меньшим расстоянием.

Учитывая это, Функция chooseBest вернет меньший путь.

Но я хочу улучшить его, потому что он будет искать во всем списке небольшое число, и это пустая трата, потому что minim занимает эту позицию. Например, minim равен 2, но он оценивает список TSP с 100 путями, я хочу немедленно вернуться к 2 и разбить l oop, но return не работает ...

Ответы [ 2 ]

2 голосов
/ 02 мая 2020

Давайте немного переделаем вашу функцию.

Во-первых, с лучшим отступом :

(defun chooseBest (TSPs dTSPs)
  (let ((minim (minPos dTSPs 0 0))
        (j 0)
        (best nil))
    (loop for i in TSPs
       do (cond ((= j minim)
                 (progn (setf best i)
                        (setq j (+ j 1))))
                (t 
                 (setq j (+ j 1)))))
    best))

Нет необходимости в progn внутри cond:

       do (cond ((= j minim)
                 (setf best i)
                 (setq j (+ j 1)))
                (t 
                 (setq j (+ j 1)))))

Увеличение j можно выполнить с помощью incf:

                 (setq j (+ j 1)))

=>

                 (incf j)

Вы можете переместить переменные let в л oop.

  (let ((minim (minPos dTSPs 0 0))
        (j 0)
        (best nil))
    (loop for i in TSPs

=>

(loop for it in TSPs
      for j from 0
      with minim = (minPos dTSPs 0 0)
      with best
      do …)

for j from 0 запускает счетчик, with … = объявляет переменную, которая вычисляется в начале (а не на каждой итерации).

Возвраты и условия

Внутри al oop мы можем использовать if…do, else…do, when и return и более одного раза. Чтобы сделать что-то в конце l oop, используйте finally.

(defun chooseBest (TSPs dTSPs)
  (loop for i in TSPs
     for j from 0
     with minim = (minPos dTSPs 0 0)
     with best
     if (= j minim)
     do (progn (setf best i)
               (incf j))
     else
     do (incf j)
     finally (return best)))

Функции для поиска списков и последовательностей

Теперь, если Вы хотите найти элемент в списке, для этого у вас есть множество функций: поиск, nth, поиск, позиция,… см. https://lispcookbook.github.io/cl-cookbook/data-structures.html#functions Поскольку minPos возвращает индекс, вы, вероятно, захотите nth index list или elt sequence index.

0 голосов
/ 02 мая 2020

Если вам нужен элемент nth списка, вы можете использовать функцию nth: (nth position list)

CL-USER 15 > (nth 0 '(((1 3600 2300) (2 3100 3300))
                      ((3 4700 5750) (22 6650 2300) (23 5400 1600))))
((1 3600 2300) (2 3100 3300))

CL-USER 16 > (nth 1 '(((1 3600 2300) (2 3100 3300))
                      ((3 4700 5750) (22 6650 2300) (23 5400 1600))))
((3 4700 5750) (22 6650 2300) (23 5400 1600))

Если вы хотите вернуться из al oop Вы можете использовать оператор return:

CL-USER > (loop for i from 10
                when (= i (expt (isqrt i) 2))
                do (return i))
16
...