明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2610|回复: 11

[原创]从列表中移去指定的元素(一个不留,支持任意嵌套表)

  [复制链接]
发表于 2009-3-30 10:04 | 显示全部楼层 |阅读模式
本帖最后由 作者 于 2009-3-30 14:29:54 编辑

从列表中移去指定的元素(一个不留,支持任意嵌套表)
  1. ;;; ============================================================================;;
  2. ;;; 函数名:         ;;
  3. ;;; RemoveItem         ;;
  4. ;;; 从列表中移去指定的元素(一个不留,支持任意嵌套表)    ;;
  5. ;;; 参数:         ;;
  6. ;;; 要从列表中移去的元素和一个列表      ;;
  7. ;;; 示例:         ;;
  8. ;;; (RemoveItem nil (list 121 nil (list "abc" nil "dde" nil 111) "aaa" nil 999));;
  9. ;;; -> (121 ("abc" "dde" 111) "aaa" 999)     ;;
  10. ;;; By 木子CAD工具 小李子  2009-3-30      ;;
  11. ;;; ============================================================================;;
  12. (defun RemoveItem (item lst / x tmplst)
  13.   (foreach x (vl-remove item lst)
  14.     (if (listp x)
  15.       (setq tmplst (append (list (RemoveItem item x)) tmplst))
  16.       (setq tmplst (append (list x) tmplst))
  17.     )
  18.   )
  19.   (reverse tmplst)
  20. )
还可以改为这样:
  1. ;;; ============================================================================;;
  2. ;;; 函数名:         ;;
  3. ;;; RemoveItem         ;;
  4. ;;; 从列表中移去指定的元素(一个不留,支持任意嵌套表)    ;;
  5. ;;; 参数:         ;;
  6. ;;; 要从列表中移去的元素和一个列表      ;;
  7. ;;; 示例:         ;;
  8. ;;; (RemoveItem nil (list 121 nil (list "abc" nil "dde" nil 111) "aaa" nil 999));;
  9. ;;; -> (121 ("abc" "dde" 111) "aaa" 999)     ;;
  10. ;;; By 木子CAD工具 小李子  2009-3-30      ;;
  11. ;;; ============================================================================;;
  12. (defun RemoveItem (item lst / x tmplst)
  13.   (foreach x (vl-remove item lst)
  14.     (if (listp x)
  15.       (setq tmplst (cons (RemoveItem item x) tmplst))
  16.       (setq tmplst (cons x tmplst))
  17.     )
  18.   )
  19.   (reverse tmplst)
  20. )
;|
(RemoveItem "" (list 121 "" (list "abc" "" "dde" "" 111) "aaa" "" 999 000))
-> (121 ("abc" "dde" 111) "aaa" 999 0)
(RemoveItem "" (list 121 "" (list "abc" "" "dde" "" 111) "aaa" "" 999 000
    (list 88 "" 9090 "" "" "AAA" "BBB" ""
          (list "ccc" "" "DDD" ""123)
    )
     )
)
-> (121 ("abc" "dde" 111) "aaa" 999 0 (88 9090 "AAA" "BBB" ("ccc" "DDD" 123)))
|;
发表于 2009-3-30 14:15 | 显示全部楼层
不错,支持一下!
发表于 2009-3-30 14:57 | 显示全部楼层

还可以这样

(defun RemoveItem (item lst)
  (mapcar '(lambda (x) (if (vl-consp x) (RemoveItem item x) x))
          (vl-remove item lst)
  )
)

 楼主| 发表于 2009-3-30 16:31 | 显示全部楼层
本帖最后由 作者 于 2009-3-30 16:50:38 编辑

在这个函数中用 atom 、listp 和 vl-consp 有何区别?
  1. (defun RemoveItem (item lst)
  2.   (mapcar '(lambda (x) (if (listp x) (RemoveItem item x) x))
  3.           (vl-remove item lst)
  4.   )
  5. )
  1. (defun RemoveItem (item lst)
  2.   (mapcar '(lambda (x) (if (atom x) x (RemoveItem item x)))
  3.           (vl-remove item lst)
  4.   )
  5. )
发表于 2009-3-30 17:24 | 显示全部楼层
本帖最后由 作者 于 2009-3-30 17:31:13 编辑

(vl-consp nil)-->nil

(listp nil)-->T

(vl-consp lst) = (and lst (listp lst))

(atom nil)-->T

(atom '(1 2))-->nil

用vl-consp,当参数为nil时省去了下一级的运算

atom 个人习惯,我一般用的比较少

 楼主| 发表于 2009-3-31 14:00 | 显示全部楼层
本帖最后由 作者 于 2009-3-31 14:07:47 编辑

请教caoyin:

_$ (list 1245 "" "add" '(1 "" 2 nil "" 3 5 "" nil 6 "" 8 . 9))
(1245 "" "add" (1 "" 2 nil "" 3 5 "" nil 6 "" 8 . 9))
如何删除点对表中的 "" nil ?

单个点对表,以及潜逃在其他表中的点对表

_$ (removeitem "" (list 1245 "" "add" '(1 "" 2 nil "" 3 5 "" nil 6 "" 8 . 9)))
; 错误: 列表错误: 9

发表于 2009-4-1 12:28 | 显示全部楼层

点对是特殊的表,作你说的运算意义不大,如果一定要写出程序楼主应该写的出

(vl-list-length '(1 . 2))->nil

;;判断表 x 是否是点对表

(and (vl-consp x) (not (vl-list-length x)))

 楼主| 发表于 2009-4-1 14:06 | 显示全部楼层

Caoyin:

我已经试过了,问题的根源是出在 vl-remove 上,虽然这个条件 (and (vl-consp x) (not (vl-list-length x)))可以用,但是到了这里 (vl-remove item lst)
,就被杀掉了,我已经通过其他方法解决了这个难题,不能用 vl-remove这个函数了。caoyin 如果不相信,可以亲自试一下!

 楼主| 发表于 2009-4-1 14:12 | 显示全部楼层
本帖最后由 作者 于 2009-4-1 14:13:14 编辑

下面是我的解决方法:有两种,但从速度比较上来看,第二种最好
  1. ;; 速度非常慢,超级慢,支持嵌套表(任意),支持表中含有点对表
  2. (defun nest-remove-if (fun lst / a )
  3.     (cond
  4.         ((apply fun (list lst)) nil)
  5.         ((atom lst) lst)
  6.         ((apply fun (list (setq a (car lst)))) (nest-remove-if fun (cdr lst)))
  7.         ((cons (nest-remove-if fun a) (nest-remove-if fun (cdr lst))))
  8.     )
  9. )
  10. ;; 速度快,比 nest-remove-if 快多了,支持嵌套表(任意),支持表中含有点对表
  11. (defun RemoveItem (pattern mylist / string index newlist)
  12.   (setq string (vl-prin1-to-string myList)
  13. pattern (vl-prin1-to-string pattern)
  14.   )
  15.   (while (setq index (vl-string-search pattern string 0))
  16.     (setq string (vl-string-subst "" pattern string))
  17.   )
  18.   (read string)
  19.   ;;(setq NewList (read string))
  20. )
  21. ;; 测试效率
  22. (defun c:test ( / lst t0)
  23.   (setq lst (list 121 "" nil
  24.     (list "abc" "" (list 777 888 '("aaa" 8888 nil "" 999 . 9) 999) "dde" "" 111)
  25.     "aaa" "" 999 000
  26.     (list 88 "" 9090 "" "" "AAA" "BBB" ""
  27.    (list "ccc" "" "DDD" "" 123 '( 222 "" nil 333 . 66666))
  28.     )
  29.     "" 55555555 nil "TTTTTT" '(44444 nil 585858 "" . 6666) "PPPPPPPP" "" nil "" "fffff" "" nil ""
  30.       )
  31.   )
  32.   
  33.   (setq t0 (getvar "TDUSRTIMER"))
  34.   (repeat 1000
  35.     (nest-remove-if '(lambda (x) (member x '("" nil))) lst)
  36.   )
  37.   (princ "\n用时")
  38.   (princ (* (- (getvar "TDUSRTIMER") t0) 86400))
  39.   (princ "秒")
  40.   
  41.   (setq t0 (getvar "TDUSRTIMER"))
  42.   (repeat 1000
  43.     (RemoveItem "" lst)
  44.     (RemoveItem nil lst)
  45.     ;;(foreach x '("" nil) (setq lst (RemoveItem x lst)))
  46.   )
  47.   (princ "\n用时")
  48.   (princ (* (- (getvar "TDUSRTIMER") t0) 86400))
  49.   (princ "秒")
  50.   
  51.   (princ)
  52. )
;|
_$ (c:test)
用时8.375秒
用时0.344秒
_$ (c:test)
用时8.219秒
用时0.359秒
_$
|;
发表于 2009-4-1 14:39 | 显示全部楼层

提醒:用 vl-prin1-to-string 是不能处理包含REAL的LIST

(setq A pi)

(setq B (RemoveItem nil (list 1 nil A)))

(/= A (cadr B))--->T

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-7 13:54 , Processed in 0.297449 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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