明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
12
返回列表 发新帖
楼主: 尘缘一生

[讨论] 关于如何代替nth问题?

[复制链接]
发表于 2021-8-19 09:06 | 显示全部楼层
本帖最后由 vectra 于 2021-8-19 09:08 编辑

nth的目的在于随机访问指定元素,受限于list数据结构,算法复杂度为O(n),效率自然是差的。

数组(Array)或字典(Map,DICT)是随机访问比较有效的结构,复杂度为O(1),可惜lisp没有直接提供这类对象

可参考
http://bbs.mjtd.com/thread-177140-1-1.html LISP中使用数组
http://bbs.mjtd.com/thread-177087-1-1.htmlLISP缓存类
http://bbs.mjtd.com/thread-170324-1-1.html打造随机访问的LISP可变长数组

通过.net扩展c#的相关数据结构供LISP使用也不失为一个比较好的想法

评分

参与人数 1明经币 +1 收起 理由
tryhi + 1 赞一个!

查看全部评分

发表于 2021-8-19 09:38 | 显示全部楼层
另外猫大的测试比较极端,基本不可能用nth来做表的遍历,比较公平一点是比较随机访问指定数据的效率,代码如下
  1. (setq biglist nil
  2.       i -1
  3. )

  4. (repeat 10000
  5.   (setq biglist (cons (setq i (1+ i)) biglist))
  6. )
  7. (setq biglist (reverse biglist))


  8. (defun test (func count)
  9.   (setq t0 (getvar "MILLISECS"))
  10.   (repeat count
  11.     (setq x (eval func))
  12.   )
  13.   (strcat "\n返回值" (itoa x) ", 用时" (itoa (- (getvar "MILLISECS") t0)) "ms")
  14. )

  15. ;;nth方式遍历表
  16. (defun ra-nth (lst index /)
  17.   (nth index lst)
  18. )

  19. ;;car cdr 方式遍历表
  20. (defun ra-car (lst index /)
  21.   (repeat index
  22.     (setq lst (cdr lst))
  23.   )
  24.   (car lst)
  25. )

  26. _$ (test '(ra-nth biglist 5000) 10000)
  27. "\n返回值5000, 用时407ms"
  28. _$ (test '(ra-car biglist 5000) 10000)
  29. "\n返回值5000, 用时24813ms"
  30. _$ (test '(ra-nth biglist 1) 10000)
  31. "\n返回值1, 用时234ms"
  32. _$ (test '(ra-car biglist 1) 10000)
  33. "\n返回值1, 用时234ms"


可见数据的位置严重影响结论,当访问表中第一个元素时,nth与car是等效的,当位置越靠近表的后端,则car的效率严重下降(car来实现nth的功能的额外代码开销)。
 楼主| 发表于 2021-8-19 10:19 | 显示全部楼层
本帖最后由 尘缘一生 于 2021-8-19 10:22 编辑
vectra 发表于 2021-8-19 09:38
另外猫大的测试比较极端,基本不可能用nth来做表的遍历,比较公平一点是比较随机访问指定数据的效率,代码 ...

对,我就是想,如何解决后部分的快速访问问题。看来目前没好办法啊。

如果:先访问一半,把后半部分倒过来,再从前访问,不知有没有快的可能性。
发表于 2021-8-19 12:08 | 显示全部楼层
尘缘一生 发表于 2021-8-19 10:19
对,我就是想,如何解决后部分的快速访问问题。看来目前没好办法啊。

如果:先访问一半,把后半部分倒 ...

不可能。

可以了解一下vlax-make-safearray 及相关函数
发表于 2021-8-19 13:31 | 显示全部楼层
不死猫 发表于 2021-8-17 22:47
循环几万次为了读一个值的程序实际应用没有这么写的。
楼主问的也是对整个表的读取遍历,只是楼主的代码 ...

换个思路,把list先转化成vector,从vector中随机取数要快,因为它不需要遍历链表。
测试了一下,和你的t2差不多
发表于 2021-8-20 12:23 | 显示全部楼层
ADFASDFADSFASDF
发表于 2021-8-20 16:44 | 显示全部楼层
baitang36 发表于 2021-8-19 13:31
换个思路,把list先转化成vector,从vector中随机取数要快,因为它不需要遍历链表。
测试了一下,和你的 ...

之前找代替append函数的时候测试过vector,
vector-append比append快一倍多的速度,但还是不能满足对效率的需求。
发表于 2021-8-21 10:17 | 显示全部楼层
NTH用起来简单。
发表于 2021-9-6 19:15 来自手机 | 显示全部楼层
(defun c:t3 (/ i lstx y)         (setq i 0 y nil)         (setq lstx nil)         (repeat 10000 (setq i(1+ i) lstx(cons i lstx)));;生成100万个元素的表         (setq t0 (getvar "TDUSRTIMER"));计时开始         (setq i 0 y nil)         (repeat 10000                 (setq x (nth i lstx))                 (setq i (1+ i))         )         (princ (strcat "\n 程序共用时" (rtos (* (- (getvar "TDUSRTIMER") t0) 86400) 2 4) "秒")) ) (defun c:t4 (/ i lstx y vlst)         (setq i 0 y nil)         (setq lstx nil)         (repeat 10000 (setq i(1+ i) lstx(cons i lstx)));;生成100万个元素的表         (setq i 0 y nil)         (setq t0 (getvar "TDUSRTIMER"));计时开始         (setq vlst (list->vector lstx))         (repeat 10000                 (setq x (vector-elt vlst i))                 (setq i (1+ i))         )         (princ (strcat "\n 程序共用时" (rtos (* (- (getvar "TDUSRTIMER") t0) 86400) 2 4) "秒")) )
发表于 2021-9-8 08:40 | 显示全部楼层
都像你们这样研究,电脑还需要大内存,高配置么,商家要饿死了。

点评

奇葩逻辑  发表于 2021-9-8 09:24
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-3 18:42 , Processed in 0.206508 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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