明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 3039|回复: 9

[函数] [已解决]表提取相同的元素并得到新表

[复制链接]
发表于 2014-11-17 02:12:23 | 显示全部楼层 |阅读模式
本帖最后由 nnzj 于 2014-11-21 17:28 编辑

寻找了很久都没有找到表提取相同元素的函数,基本都是删除相同元素或者替换相同元素的。
比如表如下:
(项目 兰花 位置)(项目 树木 位置)(项目1 兰花 位置)(项目1 树木 位置)(项目2 草地 面积)(项目2 直树 位置)
根据上表得到如下数据:
  1、比如要提取元素中的 项目 关键字得到新表(项目 兰花 位置)(项目 树木 位置)
2、又比如提取元素中的 兰花 关键字得到新表 (项目 兰花 位置)(项目1 兰花 位置)
3、又比如提取元素中的 位置 关键字得到新表(项目 兰花 位置)(项目 树木 位置)(项目1 兰花 位置)(项目1 树木 位置)(项目2 直树 位置)
请高手编辑一个提取相同元素的函数,谢谢!

发表于 2014-11-17 06:59:03 | 显示全部楼层
第一个和第二个要求用vl-remove-if-not函数,第三个用vl-sort函数。
发表于 2014-11-17 09:56:22 | 显示全部楼层
(setq lst (list '("项目" "兰花" "位置")'("项目" "树木" "位置")'("项目1" "兰花" "位置")'("项目1" "树木" "位置")'("项目2" "草地" "面积")'("项目2" "直树" "位置")))
(vl-remove-if-not '(lambda(x) (member "项目" x)) lst)
 楼主| 发表于 2014-11-18 12:50:20 | 显示全部楼层
多谢上两位,
再请教如果表形式如下:(表中的元素有不同名称用分隔符隔开)
("项目 兰花 位置" " 项目 树木 位置" "项目1 兰花 位置" "项目1 树木 位置" "项目2 草地 面积" "名称 价格" "部位1" "部位2")
同样是提取元素 项目 得到新表 ("项目 兰花 位置" "项目 树木 位置")
那怎么提取,谢谢!
 楼主| 发表于 2014-11-19 17:03:49 | 显示全部楼层
本人新手;根据列表数据得到新表格式,自定义了个函数取得不同列表样式
("项目 兰花 位置" " 项目 树木 位置" "项目1 兰花 位置" "项目1 树木 位置" "项目2 草地 面积" "名称 价格" "部位1" "部位2")
以条件 “位置”取得新表
结果一:(("项目1" "树木" "位置") ("项目1" "兰花" "位置") ("项目" "树木" "位置") ("项目" "兰花" "位置"))
结果二:("项目 兰花 位置" "项目 树木 位置" "项目1 兰花 位置" "项目1 树木 位置")
结果二是我想要的格式
(defun bbtq (mingc lst1 / lstxx newlst1 x1 x2 bas1 bss1 bas2 bss2 lstx)
;parse 分列,返回一个包含在具有分隔符的字符串所有的标记的列表
;功能:
;分列,返回一个包含在具有分隔符的字符串所有的标记的列表
;语法:
;(parse str delim)
;参数:
;一个具有分隔符的字符串和分隔符
;示例(ax:Parse (getenv "ACAD") "")
;说明:
;在AutoLISP中不能正确解释在1到255范围之外的字符代码,所以不能分列一个空分隔符的字符串。
  (defun parse (str delim / lst pos)
     (setq pos (vl-string-search delim str))
       (while pos
           (setq lst (cons (substr str 1 pos) lst)
                str (substr str (+ pos 2))
                pos (vl-string-search delim str)
        )
     )
  (if (> (strlen str) 0)
    (setq lst (cons str lst))
  )
  (reverse lst)
  )
  ;将一个字符串列表解析为1个具有分隔符的字符串
;(StrUnParse Lst Delimiter)
;参数:
;Str:要连接的列表
;Delimiter :使用的分隔符
;返回值:
;一个字符串
;示例:
;(setq a '("Harp" "Guiness" "Black and Tan"))
;(StrUnParse a ",")
;返回:
;"Harp,Guiness,Black and Tan"
;函数代码:
(defun StrUnParse (Lst Delimiter / return)
        (setq return "")
        (foreach str Lst
                (setq return (strcat return Delimiter str))
        ) ;_ end of foreach
        (substr return 2)
) ;_ end of defun语法:
(setq newlst1 nil lstxx nil x1 0 x2 0)
            (repeat (length lst1)
                   (setq bas1 (vl-princ-to-string  (nth x1 lst1)))   ;把元素转换为字符串
                   (setq bss1 (parse bas1 " "))     ;自定义函数把字符串转为按分隔符转换为表
                                   (setq newlst1 (cons bss1 newlst1))
                                   (setq x1(1+ x1))
                          )
   (setq lstx(vl-remove-if-not '(lambda(x) (member mingc x)) newlst1))
                          (repeat (length lstx)
                   (setq bas2 (nth x2 lstx))   ;把元素转换为字符串
                   (setq bss2 (StrUnParse bas2 " "))     ;自定义函数把字符串转为按分隔符转换为表
                                   (setq lstxx (cons bss2 lstxx))
                                   (setq x2(1+ x2))
                          )
)
各位老师看看还有什么简便的方法没有。上面高得复杂了。

点评

字符分割http://bbs.mjtd.com/thread-107150-1-1.html  发表于 2014-11-20 10:13
发表于 2014-11-19 21:55:17 来自手机 | 显示全部楼层
看看wcmatch函数介绍
发表于 2014-11-20 09:57:44 | 显示全部楼层
nnzj 发表于 2014-11-19 17:03
本人新手;根据列表数据得到新表格式,自定义了个函数取得不同列表样式
("项目 兰花 位置" " 项目 树木 位 ...

求结果一稍复杂,需要将长字符串分解为字符串列表,刚才写了这段分解代码,使用下面代码将字符串分解成字符串列表,然后就可以用vl-remove-if-not和vl-sort求解了。
  1. (defun str->lst(str cr / l i sr)  ;字符串分解为字符串列表,str—字符串,cr—特征分隔字符,单字符
  2.   (while (setq i (vl-string-position (ascii cr) str))
  3.     (setq sr (substr str 1 i)
  4.           str(substr str (+ i 2))
  5.     )
  6.     (if (/= sr "") (setq l (cons sr l)))
  7.   )
  8.   (reverse (cons str l))
  9. )


求结果二比较简单,使用vl-remove-it-not结合wcmatch要多少截多少,输出结果可以使用vl-sort排序,或者使用上面代码转换后再进行处理。
发表于 2014-11-20 10:36:25 | 显示全部楼层
本帖最后由 冰与火之歌 于 2014-11-20 11:13 编辑

这些表明显是有规律的 那么构造一表 long_lst ((项目 兰花 位置)(项目 树木 位置)(项目1 兰花 位置)(项目1 树木 位置)(项目2 草地 面积)(项目2 直树 位置)……)你的1、2、3条便可如此实现
(vl-remove nil (mapcar '(lambda (x) (if (not (= (car x) 项目) ) (setq x nil)) x) long_lst))
(vl-remove nil (mapcar '(lambda (x) (if (not (= (cadr x) 兰花) ) (setq x nil)) x) long_lst))
(vl-remove nil (mapcar '(lambda (x) (if (not (= (caddr x) 位置) ) (setq x nil)) x) long_lst))
 楼主| 发表于 2014-11-21 00:31:20 | 显示全部楼层
感谢各位老师的帮助,还想找个简单方法,还有函数教程说明很多不明白像下这函数组合书上可没有哦
(vl-remove nil (mapcar '(lambda (x) (if (not (= (car x) 项目) ) (setq x nil)) x) long_lst))
一、数据列表格式如下:
(setq lst (list '("项目 兰花 位置" " 项目 树木 位置" "项目1 兰花 位置" "项目1 树木 位置" "项目2 草地 面积" "名称 价格" "部位1" "部位2")))
研究了各位老师的提示,函数并不知到怎么组合直接按条件"项目"或"位置"直接得到新表:
("项目 兰花 位置" "项目 树木 位置" "项目1 兰花 位置" "项目1 树木 位置")
二、通过明经取得的函数采用变通
(setq lst (list '("项目 兰花 位置" " 项目 树木 位置" "项目1 兰花 位置" "项目1 树木 位置" "项目2 草地 面积" "名称 价格" "部位1" "部位2")))
  1、 先用函数  把字符串转为按分隔符转换为表
     如:"项目 兰花 位置"  转为表  ("项目" "兰花" "位置")
2、再用
    (vl-remove-if-not '(lambda(x) (member "位置" x)) lst)
3、取得新表
    结果:(("项目1" "树木" "位置") ("项目1" "兰花" "位置") ("项目" "树木" "位置") ("项目" "兰花" "位置"))
4、再用函数  将一个字符串列表解析为1个具有分隔符的字符串
    结果:("项目 兰花 位置" "项目 树木 位置" "项目1 兰花 位置" "项目1 树木 位置")
  三、请教老师的是用简单的函数直接得到第4、步的新表。
发表于 2014-11-21 09:27:46 | 显示全部楼层
nnzj 发表于 2014-11-21 00:31
感谢各位老师的帮助,还想找个简单方法,还有函数教程说明很多不明白像下这函数组合书上可没有哦
(vl-remo ...

(vl-remove nil (mapcar... 一句是去除表中的nil(空)项,mapcar函数出来的结果是把长表中第一项不是项目(应该是字符串"项目")的项设为nil,随后去除这些空项,这是针对1楼的表的用法。
一、命令: (vl-remove-if-not '(lambda (x) (wcmatch x "项目 *,项目1 *")) lst)
("项目 兰花 位置" "项目 树木 位置" "项目1 兰花 位置" "项目1 树木 位置")
说明一下,楼主给出的lst应该直接是(setq lst '("项目.... ,list函数多余了,表中第二项前面多一个空格。
二、三、命令: (mapcar '(lambda (x) (strcat (car x) " " (cadr x) " " (caddr x))) lst1)
("项目1 树木 位置" "项目1 兰花 位置" "项目 树木 位置" "项目 兰花 位置")
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-5-23 17:13 , Processed in 0.188983 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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