Тема: Сортировка списка

Здравствуйте!
Вопрос по сортировке списка:
У меня создан список. Выглядит он так (часть списка):
[code](((138.75 202.5 0.0) (156.25 202.5 0.0)) ((138.75 170.0 0.0)
(156.25 170.0 0.0)) ((138.75 165.0 0.0) (130.0 165.0 0.0)) ((138.75 137.5 0.0)
(145.0 137.5 0.0)) ((138.75 131.25 0.0) (127.5 131.25 0.0)) ((138.75 105.0 0.0)
(156.25 105.0 0.0)) ((138.75 98.75 0.0) (130.0 98.75 0.0)) ((138.75 72.5 0.0)
(156.25 72.5 0.0)) ((138.75 67.5 0.0) (130.0 67.5 0.0)) ((156.25 255.0 0.0)
(156.25 243.75 0.0)))
[/code]
Т.е. каждый элемент списка состоит из (х1 y1 z1) (x2 y2 z2).
Мне нужно для выполнения следущих задач отсортировать список сначала по х1, потом по х2 и затем по y1. Используя команду vl-sort получается отсортировать только по какой-то одной координате. Результат (по х1 например) получается такой при записи в txt-файл:
[code]93.75 211.25 93.75 205.00
93.75 178.75 93.75 172.50
93.75 146.25 93.75 140.00
100.00 255.00 156.25 255.00
100.00 246.25 155.00 246.25
100.00 232.50 210.00 232.50
105.00 211.25 93.75 211.25
127.50 208.75 127.50 200.00
127.50 167.50 127.50 176.25
130.00 172.50 130.00 170.00
130.00 140.00 130.00 137.50
133.75 220.00 133.75 217.50
133.75 217.50 133.75 213.75
133.75 188.75 133.75 185.00
133.75 185.00 133.75 180.00
133.75 151.25 133.75 148.75[/code]
Я использую следующую функцию:
[code](setq spisokl1 (vl-sort spisokl1
               (function (lambda (l1 l2)
                         (< (caar l1) (caar l2))       ; возрастание координаты х1
                        ;(< (caadr l1) (caadr l2))   ; возрастание координаты x2
                        ;(< (cadar l1) (cadar l2))   ; возрастание координаты y1
                         );end lambda
               );end function
               );end vl-sort
);end setq[c/ode]
Если убрать точки с запятой, то сортировка осуществится по у1. Использование функции and, т.е. [code](and (< (caar l1) (caar l2)) (< (caadr l1) (caadr l2)) (< (cadar l1) (cadar l2)))[/code] также не помогает.
Подскажите что можно сделать в данной ситуации. Возможно ли задуманное?

Re: Сортировка списка

Может такое поможет

(defun z-lst-sorting-priority-function (lst-priority-function
                    lst
                    /
                    _z-sorting-priority-function-p
                    a1
                    a2
                    b1
                    b2
                    x
                    )
;;;  Сортировка списка с приоритетами
  ;|(z-lst-sorting-priority-function
  '(("(nth 0 x)" "<") ("(nth 1 x)" ">") ("(nth 2 x)" "<"))
  '((-1 0 0)(0 0 0) (1 0 0) (0 1 0)(0 2 0)(0 3 0)(1 1 0) (0 0 1)))|;
  (defun _z-sorting-priority-function-p    (lst-priority-function /)
    (cond
      ((not lst-priority-function) nil)
      (t
       (setq x    a1
         b1    (eval (read (caar lst-priority-function)))
         x    a2
         b2    (eval (read (caar lst-priority-function)))
         ) ;_ setq
       (cond
     ((or (and (= (cadar lst-priority-function) ">") (> b1 b2))
          (and (= (cadar lst-priority-function) "<") (< b1 b2))
          ) ;_ or
      t
      )
     ((or (and (= (cadar lst-priority-function) ">") (< b1 b2))
          (and (= (cadar lst-priority-function) "<") (> b1 b2))
          ) ;_ or
      nil
      )
     (t
      (_z-sorting-priority-function-p (cdr lst-priority-function))
      )
     ) ;_ cond
       )
      ) ;_ cond
    ) ;_sorting-priority-function-p
  (vl-sort
    lst
    (function (lambda (a1 a2)
        (_z-sorting-priority-function-p lst-priority-function)
        ) ;_ lambda
          ) ;_ function
    ) ;_ vl-sort
  ) ;_ defun

Re: Сортировка списка

> Maxim
В вашем случае параметры задаются примерно так (проверь)

(z-lst-sorting-priority-function
   '(("(caar x)" "<") ("(caadr x)" "<") ("(cadar x)" "<"))
   lst
   ) ;_ z-lst-sorting-priority-function

Есть ещё другие методы сортировки (может быть быстрее), но на моё мнение они сильно зависят от типов входных данных. А мне захотелось чего-то универсального.
Уважаемые ГУРУ я прекрасно понимаю что функция написана с ошибками в объявлениях переменных, но небыло времени исправлять(и она всётаки работает).

Re: Сортировка списка

Спасибо за вариант. У меня правда ничего не получилось из-за нехватки знаний. Есть ли другие предложения?
Ребята, выручайте! Тип входных данных - координаты линий

Re: Сортировка списка

Результат выполнения с функции при использовании используя > ZZZ (2005-03-17 12:13:24) где вместо lst вставил исходные данные приведенных в > Maxim (2005-03-17 11:04:15)
получил результат
(((138.75 131.25 0.0) (127.5 131.25 0.0))
  ((138.75 67.5 0.0) (130.0 67.5 0.0))
  ((138.75 98.75 0.0) (130.0 98.75 0.0))
  ((138.75 165.0 0.0) (130.0 165.0 0.0))
  ((138.75 137.5 0.0) (145.0 137.5 0.0))
  ((138.75 72.5 0.0) (156.25 72.5 0.0))
  ((138.75 105.0 0.0) (156.25 105.0 0.0))
  ((138.75 170.0 0.0) (156.25 170.0 0.0))
  ((138.75 202.5 0.0) (156.25 202.5 0.0))
  ((156.25 255.0 0.0) (156.25 243.75 0.0))
  )
правильно?

Re: Сортировка списка

Результат - тот, который нужен. Класс!
Т.е. мне надо вместо списка lst вставить свой полученный список. Но тогда у меня программа выдает ошибку объявления переменных.

Re: Сортировка списка

Вроде исправил (ошибки у меня и так невыдавались)

(defun z-lst-sorting-priority-function (lst-priority-function
                    lst
                    /
                    _z-sorting-priority-function-p
                    )
;;;  Сортировка списка с приоритетами
  ;|(z-lst-sorting-priority-function
  '(("(nth 0 x)" "<") ("(nth 1 x)" "<") ("(nth 2 x)" "<"))
  '((-1 0 0)(0 0 0) (1 0 0) (0 1 0)(0 2 0)(0 3 0)(1 1 0) (0 0 1)))|;
  (defun _z-sorting-priority-function-p
     (lst-priority-function a1 a2 / b1 b2 x)
    (cond
      ((not lst-priority-function) nil)
      (t
       (setq x    a1
         b1    (eval (read (caar lst-priority-function)))
         x    a2
         b2    (eval (read (caar lst-priority-function)))
         ) ;_ setq
       (cond
     ((or (and (= (cadar lst-priority-function) ">") (> b1 b2))
          (and (= (cadar lst-priority-function) "<") (< b1 b2))
          ) ;_ or
      t
      )
     ((or (and (= (cadar lst-priority-function) ">") (< b1 b2))
          (and (= (cadar lst-priority-function) "<") (> b1 b2))
          ) ;_ or
      nil
      )
     (t
      (_z-sorting-priority-function-p (cdr lst-priority-function) a1 a2)
      )
     ) ;_ cond
       )
      ) ;_ cond
    ) ;_sorting-priority-function-p
  (vl-sort
    lst
    (function
      (lambda (a1 a2)
    (_z-sorting-priority-function-p lst-priority-function a1 a2)
    ) ;_ lambda
      ) ;_ function
    ) ;_ vl-sort
  ) ;_ defun

Re: Сортировка списка

> Maxim
а может доделать первоначальный вариант:

(setq spisokl1 '(((138.75 202.5 0.0) (156.25 202.5 0.0))
                 ((138.75 170.0 0.0) (156.25 170.0 0.0))
                 ((138.75 165.0 0.0) (130.0 165.0 0.0))
                 ((138.75 137.5 0.0) (145.0 137.5 0.0))
                 ((138.75 131.25 0.0) (127.5 131.25 0.0))
                 ((138.75 105.0 0.0) (156.25 105.0 0.0))
                 ((138.75 98.75 0.0) (130.0 98.75 0.0))
                 ((138.75 72.5 0.0) (156.25 72.5 0.0))
                 ((138.75 67.5 0.0) (130.0 67.5 0.0))
                 ((156.25 255.0 0.0) (156.25 243.75 0.0))
                )
)
(setq spisokl1 (vl-sort spisokl1
                        (function (lambda (l1 l2)
                                    (and (<= (caar l1) (caar l2))
                                         (<= (caadr l1) (caadr l2))
                                         (<= (cadar l1) (cadar l2))
                                    )
                                  )
                        )
               )
)

или я не понял проблему?

Re: Сортировка списка

Может тогда и я не понял проблему

> Maxim
У вас не удачный пример, результат у меня получился одинаков с > ЯR (2005-03-18 15:08:56)

> ЯR
проверьте результаты

(z-lst-sorting-priority-function
  '(("(nth 0 x)" "<") ("(nth 1 x)" "<") ("(nth 2 x)" "<"))
  '((-1 0 0)(0 0 0) (1 0 0) (0 1 0)(0 2 0)(0 3 0)(1 1 0) (0 0 1)))
  ;А теперь ваш фрагмент
(vl-sort
    '((-1 0 0) (0 0 0) (1 0 0) (0 1 0) (0 2 0) (0 3 0) (1 1 0) (0 0 1))
    '(lambda (a1 a2)
       (and (<= (nth 0 a1) (nth 0 a2))
        (<= (nth 1 a1) (nth 1 a2))
        (<= (nth 2 a1) (nth 2 a2))
        ) ;_ and
       ) ;_ lambda
    ) ;_ vl-sort

Re: Сортировка списка

> ZZZ
Да, ZZZ - прав, что-то я тут тормознул, должно быть так:

(vl-sort
  '((-1 0 0) (0 0 0) (1 0 0) (0 1 0) (0 2 0) (0 3 0) (1 1 0) (0 0 1))
  '(lambda (a1 a2)
     (or (< (nth 0 a1) (nth 0 a2))
         (and (= (nth 0 a1) (nth 0 a2))
              (or (< (nth 1 a1) (nth 1 a2))
                  (and (= (nth 1 a1) (nth 1 a2))
                       (< (nth 2 a1)
                          (nth 2 a2)
                       )
                  )
              )
         )
     )
   )
)

соответстенно, в исходном получается так:

(setq spisokl1 (vl-sort spisokl1
                        (function (lambda (l1 l2)
                                    (or (< (caar l1) (caar l2))
                                        (and (= (caar l1) (caar l2))
                                             (or (< (caadr l1) (caadr l2))
                                                 (and (= (caadr l1) (caadr l2))
                                                      (< (cadar l1)
                                                         (cadar l2)
                                                      )
                                                 )
                                             )
                                        )
                                    )
                                  )
                        )
               )
)

если опять не промазал (никому нельзя доверять, даже - себе).

Re: Сортировка списка

Ребята, огромное вам (ZZZ, ЯR), спасибо. У меня все получилось. Последний вариант - то что надо. А таким же макаром и четвертую координату можно отсортировать?
Вот программу, которую, ZZZ, Вы написали в начале, я до сих пор понять не могу. Если есть время, поясните словами, что делается в каждой строке и обязательно ли функции должны так называться. Еще раз, покорнейше благодарю. Может еще пообщаемся - задачи стоят глобальные.

Re: Сортировка списка

Maxim пишет:

А таким же макаром и четвертую координату можно отсортировать?

Конечно, просто добавить 2 строки, по аналогии.