找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

楼主: doubao

[LISP函数]:SET 函数有什么用?

[复制链接]
 楼主| 发表于 2005-9-4 21:21:37 | 显示全部楼层
我做了一个试验:

在一个新图里做了三个块,
块 111  是一个矩形, 然后矩阵为70000个
块 222  是一个圆, 然后矩阵为50000个
块 333  是一个椭圆, 然后矩阵为40000个


结果:

用set函数编的统计程序(11楼程序)大约用了 17 秒,

用13楼程序大约用了 550 秒。


(感谢版主加分!)


其实13楼程序也可以改进一下为累加器方式的。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 6530个

财富等级: 富甲天下

发表于 2005-9-5 12:01:35 | 显示全部楼层
实际上13楼的程序就是累加器的问题,我修改了一下,速度比11楼的程序快一些:
[php](defun c:sumblk        (/ ss sl i ent  bnm bl)
  ;;
  (if (setq ss (ssget '((0 . "insert"))))
    (progn
      (setq sl (sslength ss)
            i  0
      )
       (setq t1 (getvar "cdate"))   ;;;;
     (repeat sl
        (setq ent (entget (ssname ss i))
              i          (1+ i)
              bnm (strcat "EA_" (cdr (assoc 2 ent)))
        )
        (if (eval (read bnm))
          (set (read bnm) (1+ (eval (read bnm))))
          (set (read bnm) 1)
        )
        (setq bl (if (not (vl-position bnm bl))
                   (cons bnm bl)
                   bl
                 )
        )
      )
      (if bl
        (progn (mapcar '(lambda        (x)
                          (princ (strcat "\n图块" (substr x 4) "数量: "))
                          (princ (eval (read x)))
                        )
                       bl
               )
               (mapcar '(lambda (x) (set (read x) nil)) bl);_这个要定义到 *error* 中释放变量
               (setq bl nil);_也要加入到 *error* 中
        )
      )
    )
  )
      (setq t2 (getvar "cdate"))   ;;;;
      (princ "\n")    ;;;;
      (princ (rtos (* 100000 (- t2 t1) 2 8)))  ;;;;
  (princ)
)

;|   Written By Eachy 2004.1.12
功能: 图块数量统计;;
说明: 根据点取的典型图块统计, 可以多选 ;;
|;
(defun c:Ea:BlkNum  (/ ss ssl i bn bl pos)
  (princ "\n拾取统计范围[All - 全选].....")
  (if (setq ss (ssget '((0 . "insert"))))
    (progn
      (setq ssl        (sslength ss)
            i        -1
      )
      (setq t1 (getvar "cdate"))   ;;;;
      (repeat ssl
        (setq bn (cdr (assoc 2 (entget (ssname ss (setq i (1+ i)))))))
        (if bl
          (if (setq pos (assoc bn bl))
            (setq bl (subst (cons bn pos) pos bl))
            (setq bl (append (list (list bn)) bl))
          )
          (setq bl (list (list bn)))
        )
      )
      (mapcar '(lambda (x)
                 (princ (strcat "\n图块" (car x) "数量: "))
                 (princ (length x))
               )
              bl
      )
    )
  )
      (setq t2 (getvar "cdate"))   ;;;;
      (princ "\n")    ;;;;
      (princ (rtos (* 100000 (- t2 t1) 2 8)))  ;;;;
  (princ)
)

;;;;修改程序
(defun c:BlkNum  (/ ss ssl i bn bl pos)
  (princ "\n拾取统计范围[All - 全选].....")
  (if (setq ss (ssget '((0 . "insert"))))
    (progn
      (setq ssl        (sslength ss)
            i        -1
      )
      (setq t1 (getvar "cdate"))   ;;;;
      (repeat ssl
        (setq bn (cdr (assoc 2 (entget (ssname ss (setq i (1+ i)))))))
        (if bl
          (if (setq pos (assoc bn bl))
            (setq bl (subst (cons bn (1+ (cdr pos))) pos bl))
            (setq bl (cons (cons bn 1) bl))
          )
          (setq bl (list (cons bn 1)))
        )
      )
      (mapcar '(lambda (x)
                 (princ (strcat "\n图块" (car x) "数量: "))
                 (princ (cdr x))
               )
              bl
      )
    )
  )
      (setq t2 (getvar "cdate"))   ;;;;
      (princ "\n")    ;;;;
      (princ (rtos (* 100000 (- t2 t1) 2 8)))  ;;;;
  (princ)
)[/php]

前面是原来程序,最后一段是修改后程序。

其实很简单,“setq”是对一个(或多个)固定名称的变量赋值,而“set”是对一个不定名称的变量赋值,即名称也是可以运算得到的,其实这样更占用内部资源,且不利于释放,所以应该是不得已而为之。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 593个

财富等级: 财运亨通

发表于 2005-9-5 12:09:36 | 显示全部楼层
如果有数量很多的不同图块,每个块的数量少,这时的表用 Assoc 检索不知不觉效率如何
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 6530个

财富等级: 富甲天下

发表于 2005-9-5 12:30:45 | 显示全部楼层
最初由 eachy 发布
[B]如果有数量很多的不同图块,每个块的数量少,这时的表用 Assoc 检索不知不觉效率如何 [/B]


使用assoc检索应该是比较高效率的,同样使用vl-position函数也是检索,程序中替换是容易的,但与set函数无关,也许vl函数在al函数基础上有较多的优化,会快一些也不一定。程序还涉及其它函数以及算法,影响速度的主要因数应该是算法而不是函数。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 593个

财富等级: 财运亨通

发表于 2005-9-5 14:23:47 | 显示全部楼层
的确,算法很重要,不过对Lisp程序除了算法之外,在批量处理的时候还要对函数进行比选,使用高效的函数,积少成多,最终才能得到Lisp方法的最高效程序。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-5 17:00:54 | 显示全部楼层
ll_j 指出 “set 是对一个不定名称的变量赋值,即名称也是可以运算得到的,其实这样更占用内部资源,且不利于释放,所以应该是不得已而为之。”

这段话引出两个问题

1、什么时候“不得已而为之”用SET函数? 还有其他更好的例子么?

2、有没有什么好的办法释放由SET函数设置的变量?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 6530个

财富等级: 富甲天下

发表于 2005-9-5 20:06:53 | 显示全部楼层
最初由 doubao 发布
[B]ll_j 指出 “set 是对一个不定名称的变量赋值,即名称也是可以运算得到的,其实这样更占用内部资源,且不利于释放,所以应该是不得已而为之。”

这段话引出两个问题

1、什么时候“不得已而为之”用SET函数? ... [/B]


1.更好的例子无法举,用到时的确会感到乐趣,就是联机帮助中所说的“间接”赋值。我所记得的论坛最早提到set函数是关于“数组”的,具体不记得了,大意就是将“内容1”赋值到如变量“P1”,“内容2”赋值到变量“P2”....,就如:
  1. ...
  2. (setq i (1+ i) j (1+ j))
  3. (set (read (strcat "p" (itoa i))) (* 3  j^2))
  4. ...

当然,这个例子最好的解决办法还是使用表,但有时的确会有“字符串”、“序列”与“值”存在“联动”关系,使用一下set可能大大精简代码。
2.关于释放,不是没有办法,可以再“制造”这个“序列”(如P1、P2...),然后逐个赋值为nil,在c:sumblk函数中,“(mapcar '(lambda (x) (set (read x) nil)) bl)”就是释放变量,前提是这些变量名(就是“EA_块名”)已经被预先收集在一个表中了。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-5 20:46:44 | 显示全部楼层
有点开窍了。多谢 ll_j  !!!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-9-5 21:39:40 | 显示全部楼层

  1.   [FONT=courier new]
  2. (defun c:bkc2 (/ i ss e nm sym lst )  
  3.   (princ "\nbkc全图块统计-v2.0b(set方法)\n 选择块<回车全选>:")
  4.   (or(setq ss (ssget '((0 . "INSERT"))))
  5.      (setq ss (ssget "x" '((0 . "INSERT"))))
  6.   );;
  7.   (setq i -1)
  8.   (while (setq e (ssname ss (setq i (1+ i))))
  9.     ;;(setq nm  (cdr(assoc 2 (entget e)))
  10.     (setq nm  (strcat "块" (cdr(assoc 2 (entget e))))
  11.           sym (read nm))
  12.     (if (eval sym)
  13.       (set sym (1+ (eval sym)))
  14.       (progn
  15.         (set sym 1)
  16.         (setq lst (cons sym lst))
  17.       )
  18.     )
  19.   )
  20.   (princ "\n 块名      数量 ")
  21.   (mapcar '(lambda(x)(print x)(princ " 数量为 ")(princ (eval x))) lst)
  22.   (mapcar '(lambda(x)(set x nil)) lst)
  23.   (princ)
  24. )
  25.   [/FONT]
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 593个

财富等级: 财运亨通

发表于 2005-9-5 23:20:56 | 显示全部楼层
假如块名中 有纯数字的或者有 “PI” “TYPE” 。。。。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2005-9-6 00:09:49 | 显示全部楼层
哦,忘了
(setq nm  (cdr(assoc 2 (entget e)))
改为 
(setq nm  (strcat "块" (cdr(assoc 2 (entget e))))
就ok (已更新)
再贴一个,也是用表先保存块名(不删同名项),然后计数(mapcar一句),效率不知道怎么样,输出结果块名排序,看起来美观一点:),与大家分享。

  1.   [FONT=courier new]
  2. (defun c:bkc (/ i fil ss e nms nm lst)
  3.   (princ "\nbkc全图块统计-v2.0---狂刀.2005.8m \n 选择块<回车全选>:")
  4.   (setq i -1 fil '((0 . "INSERT")))
  5.   (or(setq ss (ssget fil))
  6.      (setq ss (ssget "x" fil))
  7.   )
  8.   (while (setq e (ssname ss (setq i (1+ i))))
  9.     (setq nms (cons (cdr(assoc 2 (entget e))) nms))
  10.   )
  11.   (setq nms (vl-sort nms '<));;排序.
  12.   (setq nm (car nms) i 0 lst nil)
  13.   (mapcar '(lambda(x)(if (= nm x)(setq i(1+ i))(setq lst (cons (list nm i) lst) i 1 nm x))) nms)
  14.   (princ "\n 块名     数量 ");;
  15.   (mapcar '(lambda(x)(print (car x))(princ "  ")(princ (cadr x))) lst);;
  16.   (princ);; lst 返回值可改为表用于程序中.
  17. ) 
  18.   [/FONT]
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-9-24 18:18 , Processed in 0.369664 second(s), 44 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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