明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2840|回复: 17

[讨论] N维表排序及自定义顺序

[复制链接]
发表于 2022-9-17 09:04:07 | 显示全部楼层 |阅读模式
本帖最后由 llsheng_73 于 2022-9-19 17:55 编辑

对一维表排序简单,(vl-sort l '<)

对二维表复杂点,通常写法(vl-sort l'(lambda(x y)(if(=(car x)(car y))(<(cadr x)(cadr y)(<(car x)(car y)))
那么对于三维甚至多维呢?难道象二维表那样一直套下去?
当然不是不行,但存在的问题很明显,一是不能通用,二是代码很长,多维应该能把自己先搞晕。
如果反过来,对排序参数x,y先去除相同的,再对它们进行排序是不是就可以通用了呢?
有想法就上码,经测试想法是正确的
  1. (defun sortn(l fun)
  2. (vl-sort l'(lambda(x y)(while(and(=(car x)(car y))(cdr x)(cdr y))(setq x(cdr x)y(cdr y)))(fun(car x)(car y)))))

这样虽然解决了二维到多维的问题,但明显不支持一维表排序了
  1. (defun sortn(l fun)
  2. (or(listp(car l))(setq l(mapcar'list l)))
  3. (vl-sort l'(lambda(x y)(while(and(=(car x)(car y))(cdr x)(cdr y))(setq x(cdr x)y(cdr y)))(fun(car x)(car y)))))

但缺点同样明显,所有维数的排序依据都是相同的,如果要按指定维数指定依据的话,首先应该按维数给定排序依据,即 fun应该为funs
  1. (defun sortn(l funs)
  2.   (or(listp(car l))(setq l(mapcar'list l)))
  3.   (or(listp funs)(setq funs(list funs)))
  4.   (while(<(length funs)(length(car l)))
  5.     (setq funs(cons(car funs)funs)))
  6.   (vl-sort l'(lambda(x y / n)(setq n 0)
  7.        (while(and(=(car x)(car y))(cdr x)(cdr y))(setq x(cdr x)y(cdr y)n(1+ n)))((nth n funs)(car x)(car y)))))

对于菜卷鱼提出的很关键的一个问题,先排序第几维,另外根据masterlong的思路,增加容差,并修改为只排序指定维数
再增加一个自定义序列支持,让就它彻底成为EXCEL的排序吧,感觉白折腾了
  1. (defun sortn(l keys funs fuzz / n mposition);;;keys关键字列号要么为nil要么为表,funs各个关键字的排序方式,通常为<或>,也可以为自定义序列,比如'("张三""李四")
  2.   (defun mposition(e l / i)(if(setq i(vl-position e l))i(length l)))
  3.   (or(listp(car l))(setq l(mapcar'list l)))
  4.   (or(listp funs)(setq funs(list funs)))
  5.   (if(zerop(setq n(length keys)))(setq n(length(car l))))
  6.   (while(<(length funs)n)(setq funs(cons(car funs)funs)))
  7.   (mapcar(function(lambda(x)(nth x l)))
  8.          (vl-sort-i(if keys(mapcar(function(lambda(x)(mapcar'(lambda(y)(nth y x))keys)))l)l)
  9.                    (function(lambda(x y / n )(setq n 0)
  10.                       (while(and(equal(car x)(car y)fuzz)(cdr x)(cdr y))(setq x(cdr x)y(cdr y)n(1+ n)))
  11.                               (if(listp(setq n(nth n funs)))
  12.                                 (<(mposition(car x)n)(mposition(car y)n))
  13.                                 (n(car x)(car y))))))))

对于需要排序的表比较大的情况,是否可以考虑直接调用EXCEL来排序?

(SORTN '((2 2 3 4)(1 1 1 7)(2 2 1 5)(1 1 0 4))'(1 3)(list > <)0)
((2 2 3 4) (2 2 1 5) (1 1 0 4) (1 1 1 7))


(SORTN'(("上海""崇明区")("北京""朝阳区")("上海""静安区")("北京""房山区")("重庆""酉阳")("四川""成都"))nil'(("北京""上海")("静安区""朝阳区""房山区""崇明区""成都""酉阳"))0)
(("北京" "朝阳区") ("北京" "房山区") ("上海" "静安区") ("上海" "崇明区") ("四川" "成都") ("重庆" "酉阳"))











评分

参与人数 2明经币 +1 金钱 +15 收起 理由
e2002 + 15 很给力!
guosheyang + 1 很给力!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2022-9-19 14:32:28 | 显示全部楼层
本帖最后由 masterlong 于 2022-9-19 14:59 编辑

  1. ;999公共函数
  2. ;|
  3. my_px   给定排序优先级和排序方式,对多维坐标表进行排序  
  4. (my_px pobiao biao1 biao2 fuzz)

  5. pobiao----点坐标集合,每一个元素均为n维坐标点
  6. biao1-----每一维的排序优先级,是一个0~n-1的整数表,数字越小级别越高。如'(1 2 0) 表示Z优先级最高,X其次,Y最低
  7. biao2-----各维的排序关系,元素个数n-1,元素为“>”或“<”。如'(> > <) 表示X按大小排序,Y按大小排序,Z按小大排序
  8. fuzz------容差值。

  9. 实例:
  10. 二维坐标从上到下从左到右,容差为0【这是人阅读的习惯模式】
  11. (my_px '((6 4)(7 3)(6 2)(7 9)(2 2)(1 6)) '(1 0) '(< >) 0)
  12. 返回:((7 9) (1 6) (6 4) (7 3) (2 2) (6 2))

  13. 实例:
  14. 二维坐标从上到下从左到右,容差为1
  15. (my_px '((6 4)(7 3)(6 2)(7 9)(2 2)(1 6)) '(1 0) '(< >) 1)
  16. 返回:((7 9) (1 6) (6 4) (2 2) (6 2) (7 3))

  17. 实例:
  18. 四维坐标指定方式排序
  19. (my_px '((2 2 3 4)(1 1 1 7)(2 2 1 5)(1 1 0 4)) '(2 1 0 3) '(< > > <) 0)
  20. 返回:((2 2 3 4) (2 2 1 5) (1 1 1 7) (1 1 0 4))
  21. |;
  22. ;;
  23. (defun my_px( pobiao biao1 biao2 fuzz )
  24.   (vl-sort pobiao
  25.      ''((a b)
  26.           (setq n (length biao1))
  27.           (setq i 0)
  28.           (while (< i n)
  29.             (setq id (vl-position i biao1))    ;;比较维度
  30.             (setq bj (nth id biao2))           ;;比较符号
  31.             
  32.             ;;ab比较
  33.             (setq aa (nth id a))
  34.             (setq bb (nth id b))
  35.             (if (> (abs (- aa bb)) fuzz)
  36.               (progn
  37.                 (setq i n)
  38.                 ((eval bj) aa bb)
  39.               )
  40.               (setq i (1+ i))
  41.             )
  42.           )
  43.      )
  44.   )
  45. )



回复 支持 1 反对 0

使用道具 举报

发表于 2022-9-19 15:05:45 | 显示全部楼层
  1. ;999公共函数
  2. ;|
  3. my_px_v2   给定排序优先级和排序方式,对多维坐标表进行排序   (允许对某个维度忽略排序)
  4. (my_px_v2 pobiao biao1 biao2 fuzz)

  5. pobiao----点坐标集合,每一个元素均为n维坐标点
  6. biao1-----每一维的排序优先级,是一个0~n-1的整数表,数字越小级别越高。如'(1 2 0) 表示Z优先级最高,X其次,Y最低
  7. biao2-----各维的排序关系,元素个数n-1,元素为“>”或“<”或nil,nil表示对应维度不排序。如'(> > nil) 表示X按大小排序,Y按大小排序,Z不进行排序
  8. fuzz------容差值。

  9. 实例:
  10. 二维坐标从上到下从左到右,容差为0【这是人阅读的习惯模式】
  11. (my_px_v2 '((6 4)(7 3)(6 2)(7 9)(2 2)(1 6)) '(1 0) '(< >) 0)
  12. 返回:((7 9) (1 6) (6 4) (7 3) (2 2) (6 2))

  13. 实例:
  14. 二维坐标从上到下从左到右,容差为1
  15. (my_px_v2 '((6 4)(7 3)(6 2)(7 9)(2 2)(1 6)) '(1 0) '(< >) 1)
  16. 返回:((7 9) (1 6) (6 4) (2 2) (6 2) (7 3))

  17. 实例:
  18. 四维坐标指定方式排序1
  19. (my_px_v2 '((2 2 3 4)(1 1 1 7)(2 2 1 5)(1 1 0 4)) '(2 1 0 3) '(< > > <) 0)
  20. 返回:((2 2 3 4) (2 2 1 5) (1 1 1 7) (1 1 0 4))

  21. 实例:
  22. 四维坐标指定方式排序2
  23. (my_px_v2 '((2 2 3 4)(1 1 1 7)(2 2 1 5)(1 1 0 4)) '(2 1 0 3) '(< > < <) 0)
  24. 返回:((1 1 0 4) (2 2 1 5) (1 1 1 7) (2 2 3 4))

  25. 实例:
  26. 四维坐标指定方式排序3
  27. (my_px_v2 '((2 2 3 4)(1 1 1 7)(2 2 1 5)(1 1 0 4)) '(2 1 0 3) '(< > nil <) 0)
  28. 返回:((2 2 3 4) (2 2 1 5) (1 1 0 4) (1 1 1 7))
  29. |;
  30. ;;
  31. (defun my_px_v2( pobiao biao1 biao2 fuzz / n i id bj aa bb )
  32.   (vl-sort pobiao
  33.         ''((a b)
  34.             (setq n (length biao1))
  35.             (setq i 0)
  36.             (while (< i n)
  37.               (setq id (vl-position i biao1))    ;;比较维度
  38.               (setq bj (nth id biao2))            ;;比较符号
  39.               
  40.               ;;ab比较
  41.               (if (null bj)
  42.                 (setq i (1+ i))
  43.                 (progn
  44.                   (setq aa (nth id a))
  45.                   (setq bb (nth id b))
  46.                   (if (> (abs (- aa bb)) fuzz)
  47.                     (progn
  48.                       (setq i n)
  49.                       ((eval bj) aa bb)
  50.                     )
  51.                     (setq i (1+ i))
  52.                   )
  53.                 )
  54.               )
  55.             )
  56.         )
  57.   )
  58. )


点评

这个主要是考虑,大多数的应用场景中,点表是3维,而排序只针对XY  发表于 2022-9-19 15:08
发表于 2022-9-17 09:41:21 | 显示全部楼层
你这个问题问得很抽象
一维表排序好说,就1个数字,可以直接排序
二维表就说不通了,是先排X位呢,还是先排Y位
三维表也是,X,Y,Z先排哪个总得有个顺序吧?
 楼主| 发表于 2022-9-17 09:48:03 | 显示全部楼层
菜卷鱼 发表于 2022-9-17 09:41
你这个问题问得很抽象
一维表排序好说,就1个数字,可以直接排序
二维表就说不通了,是先排X位呢,还是先 ...

确实这一点很重要。。。
发表于 2022-9-17 10:03:30 | 显示全部楼层
所以说搞个二维的感觉头都秃了  更别说三维了
  

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2022-9-17 10:13:12 | 显示全部楼层
l 排序次数
d 排序方向,nil 表示从左至右
f 排序方法 > , <

(setq lst '((1 2 3)(2 3 2)(3 4 1)))
(ldfsort lst 3 nil >) ==>((1 2 3) (2 3 2) (3 4 1))
(ldfsort lst 3 t >)==>((3 4 1) (2 3 2) (1 2 3))

  1. (defun ldfsort (lst l d f / ldf_sort s nf lst)
  2.   (defun ldf_sort (lst n f)
  3.     (vl-sort lst '(lambda (x y) (f (nth n x) (nth n y))))
  4.   )
  5.   (if (null d)
  6.     (setq s  -1
  7.           nf 1+
  8.     )
  9.     (setq s  l
  10.           nf 1-
  11.     )
  12.   )
  13.   (repeat l
  14.     (setq s (nf s))
  15.     (setq lst (ldf_sort lst s f))
  16.   )
  17. )

 楼主| 发表于 2022-9-17 10:17:09 | 显示全部楼层
aihuyujian 发表于 2022-9-17 10:03
所以说搞个二维的感觉头都秃了  更别说三维了

按L表中各维顺序给定排序依据,按排序优先次序给出sorts
对于先Y按增加x按减来说 (sortn l '(1 0) (list < >))
发表于 2022-9-19 14:49:17 | 显示全部楼层

感谢优化,加上了容差   代码好像更简洁了
发表于 2022-9-19 15:34:11 | 显示全部楼层
73兄的代码看着费劲
执行效率比我的高

(progn
        (time_start)
        (repeat 50000 (my_px '((2 2 3 4)(1 1 1 7)(2 2 1 5)(1 1 0 4)) '(2 1 0 3) '(< > > <) 0))
        (time_end)
)
********程序运行完成   耗时 28.07 秒********

(progn
        (time_start)
        (repeat 50000 (SORTN '((2 2 3 4)(1 1 1 7)(2 2 1 5)(1 1 0 4)) '(2 1 0 3) (list < >  > <)))
        (time_end)
)
********程序运行完成   耗时 5.44 秒********

差距还挺大
是我的代码里nth用的比较多?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-17 03:33 , Processed in 0.187967 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表