Common lisp 公共lisp中的列表位置映射

Common lisp 公共lisp中的列表位置映射,common-lisp,Common Lisp,我有3个列表,其中前两个列表大小相同,第三个列表是第一个列表的子列表。 假设list1是’(X Y Z W),list2是’(1 2 3 4),list3是’(X Z) 我需要得到第二个列表的一个子列表,该子列表没有列表1中列表3中缺少的位置,因此在本例中,结果应该是(13) 要获得元素的位置,我可以这样写: (position 'Z '(X Y Z W) :test #'equal) 这将返回元素基于0的位置。 但是我不确定如何继续我的工作 这里有两种可能的解

我有3个列表,其中前两个列表大小相同,第三个列表是第一个列表的子列表。 假设list1是’(X Y Z W),list2是’(1 2 3 4),list3是’(X Z) 我需要得到第二个列表的一个子列表,该子列表没有列表1中列表3中缺少的位置,因此在本例中,结果应该是(13)

要获得元素的位置,我可以这样写:

    (position 'Z
      '(X Y Z W)
      :test #'equal)
这将返回元素基于0的位置。
但是我不确定如何继续我的工作

这里有两种可能的解决方案,第一种是使用原始函数的二次解决方案:

(defun position-map (l1 l2 l3)
  (let ((pairs (pairlis l1 l2)))
    (mapcar (lambda (x) (cdr (assoc x pairs))) l3)))

(position-map '(x y z w) '(1 2 3 4) '(x z)) ;; => (1 3)
首先,我们创建一个包含由两个列表的元素组成的对的列表,然后我们扫描第三个列表,只获取car等于第三个列表元素的对的元素。只有当第一个列表中的元素都不同时,此方法才有效

第二种解决方案是线性的,它使用迭代,并允许在第一个列表中重复元素(但只有当第三个列表的元素作为第一个列表的元素排序时,它才起作用):


理论上,您可以遍历第三个列表,构建hast表,然后遍历第一个列表,生成“位置键控”哈希表,最后遍历第二个列表以收集正确的值。但是,您最好只是并行地迭代第二个和第三个。
(defun position-map (l1 l2 l3)
  (loop 
     for x in l1
     for y in l2
     when (eql x (car l3)) 
     collect y
     and do (pop l3)))