首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在通用Lisp中,我可以使用map函数实现将两个列表合并为一个列表吗?

在通用Lisp中,我可以使用map函数实现将两个列表合并为一个列表吗?
EN

Stack Overflow用户
提问于 2014-04-03 16:04:47
回答 2查看 196关注 0票数 1

有两份清单如下:

代码语言:javascript
复制
(setf l1 '((1 . 1) (2 . 2) (3 . 3)  (4 . 4) (5 . 5)))
(setf l2 '(2  22  4  44  6 66))    ;; this is a alist

我想把这两份清单合并为一份,例如:

代码语言:javascript
复制
((1 . 1) (2 . 22) (3 . 3)  (4 . 44) (5 . 5)  (6 . 66))

我可以使用一些Set函数,比如intersectionset-difference

但是我想用没有迭代器函数的map函数来实现,比如doloop,我不知道怎么做。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-04 09:21:46

对于列表,这看起来不是合并,而是更新:您希望用l1中指定的l2更新更新数据。

代码语言:javascript
复制
(defun update (target updates)
  "Returns a copy of the alist TARGET where the values are updated according
to the plist UPDATES."
  (mapcar (lambda (assoc)
            (let ((update (getf updates (car assoc) :not-found)))
              (if (eq update :not-found)
                  assoc
                  (cons (car assoc) update))))
          target))

如果updates大于几十个元素,那么首先应该将其转换为相对于随机查找具有更好伸缩性的数据结构。

票数 1
EN

Stack Overflow用户

发布于 2014-04-03 16:51:58

首先,您需要将l2转换为真诚的主义者:

代码语言:javascript
复制
(setq l3 (loop for (a b) on l2 by #'cddr collect (cons a b)))
==> ((2 . 22) (4 . 44) (6 . 66))

接下来,您可以对它们进行合并

代码语言:javascript
复制
(setq l4 (merge 'list l1 l3 #'< :key #'car))
==> ((1 . 1) (2 . 2) (2 . 22) (3 . 3) (4 . 4) (4 . 44) (5 . 5) (6 . 66))

现在你可以移除复本了(小心!)不必要的二次复杂度!):

代码语言:javascript
复制
(setq l5 (delete-duplicates l4 :key #'car))
==> ((1 . 1) (2 . 22) (3 . 3) (4 . 44) (5 . 5) (6 . 66))
  1. 我不认为你能用一张简单的地图就能做到这一点。
  2. 最有效的实现将使用单个手工构建的循环,而不是系统功能。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22843102

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档