在使用临时结果时将列表项目添加在一起

发布于 2025-01-28 08:08:03 字数 625 浏览 4 评论 0 原文

我有以下列表:

((a b) (c d) (e f))

要循环浏览并将列表元素组合在一起。我也有一个循环,它的工作原理与我想要的完全一样:

(loop for (x . tail) on l1
      append (loop for y in tail
                   collect (append (list '&)  x y)))

问题是,我想首先添加前两个元素,

((a b) (c d)) -> ((& a b ) (& c d) (& a b c d))

并使用此临时结果添加下一个列表,(ef)

((a b ) (c d) (a b c d) (e f)) -> ((& a b e f) (& c d e f) (& a b c d e f))

我是否必须写一个额外的功能,该功能首先调用两个元素的LOP,还是有一种循环变量可以使用临时结果?我已经尝试使用额外的功能,但是它似乎是如此W又不自然。我真的是LISP循环的新手

I have the following list:

((a b) (c d) (e f))

and want to loop through it and combine the list elements together. I also have the loop for that, which works exactly like I want to:

(loop for (x . tail) on l1
      append (loop for y in tail
                   collect (append (list '&)  x y)))

The problem is, that I want to first add the first two elements,

((a b) (c d)) -> ((& a b ) (& c d) (& a b c d))

and use this provisional result to add the next list, (e f) to it.

((a b ) (c d) (a b c d) (e f)) -> ((& a b e f) (& c d e f) (& a b c d e f))

Would I have to write an extra function, that calls the lop with two elements first or is there a kind of loop variable to use a provisional result? I've tried using an extra function but it just seems so wordy and unnatural. I'm really new to Lisp Loops

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷血 2025-02-04 08:08:03

问题陈述

OP要求模糊。给定输入列表,尚不完全清楚输出应该是什么;在问题和评论中,OP提供的示例输出中的示例输出中的不一致使这更加复杂。

OP从结合了输入列表元素的循环开始:

(loop for (x . tail) on l1
      append (loop for y in tail
                   collect (append (list '&)  x y)))

此循环不会产生OP预期输出中显示的那种对:

((a b) (c d)) -> ((& a b ) (& c d) (& a b c d))

相反,上述输出是:

((a b) (c d)) -> ((& a b c d))

上操作的最终结果)(cd)(ef))似乎是((& abef)(& cdef)(& abcdef))。但这似乎缺少列表(& abcd)

在评论中似乎是在列表上操作的结果((ab)(cd)(ef)(gh))应为((& ab)(& cd) (& abcd)(& abef)(& cdef)(& abcdef)(& abgh)(& cdgh)(& abcdgh)(& abefgh)(& abefgh)(& cdefgh) )。此结果包括列表(& ab)(& cd),似乎与原始操作没有任何连接。此外,(& ef)(& gh)在此结果中神秘地没有。

不过,从中,OP希望收集包含第一个操作生成的所有原始组合的结果,以及在 cdr 降低的一系列列表中运行的结果,并由由加入每个列表的第一对。

我可能

没有声称这是一个最佳解决方案,是一个特别好的解决方案,或者它甚至解决了OP的问题,因为它在这里不是很清楚。我只声称这可以是使用OP的原始组合操作的 a 解决方案,这很清楚。我怀疑可以通过从一开始就重新考虑问题来找到更好的解决方案。

可以将OP操作放置在函数中:

(defun combiner (xss)
  (loop for (x . tail) on xss
        append (loop for y in tail
                     collect (append x y))))

此处添加的符号'& 被忽略;这只会在我们结合列表元素的同时混淆问题,并且完成后可以轻松地将符号预先添加到结果列表中。

无需使用 combiner 在列表的前两个元素上操作,因为结果始终只是这两个列表元素的串联。编写一个通过串联前两个元素来转换列表的函数将很有用。 Singleton列表应转换为 nil

(defun fancy-transform (xss)
  (unless (null (cdr xss))
    (cons (append (first xss) (second xss))
          (cddr xss))))

现在我们准备编写一个使用 combiner 创建所需结果的函数:

(defun fancy-combiner (xss)
  (mapcar (lambda (xs) (cons '& xs))
          (remove-duplicates
           (loop for uss on xss
                 append (loop for vss on uss by #'fancy-transform
                              append (combiner vss)))
           :test #'equal)))

操作位于 loop 宏。需要调用删除duplicates ,因为循环的结果包含重复项,并且使用 mapcar 的调用用于预处'& 结果中每个列表的符号。

外循环将输入列表的较小版本逐渐馈入内部循环;这些列表中的每个列表均由 combiner 转换,然后由 fancy-transform 缩小,该通过附加前两个元素或返回 nil 来减少列表。当达到单身清单时(结束迭代)。

将进度作为输入列表进行处理可能会有所帮助。此花式组合插图函数不会删除重复项或在结果中的列表中预先一个符号:

(defun fancy-combiner-illustrated (xss)
  (loop for uss on xss
        do (format t "~%USS: ~A" uss)
        append (loop for vss on uss by #'fancy-transform
                     do (format t "~%VSS: ~A" vss)
                     append (combiner vss))))
CL-USER> (fancy-combiner-illustrated '((a b) (c d) (e f) (g h)))

USS: ((A B) (C D) (E F) (G H))
VSS: ((A B) (C D) (E F) (G H))
VSS: ((A B C D) (E F) (G H))
VSS: ((A B C D E F) (G H))
VSS: ((A B C D E F G H))
USS: ((C D) (E F) (G H))
VSS: ((C D) (E F) (G H))
VSS: ((C D E F) (G H))
VSS: ((C D E F G H))
USS: ((E F) (G H))
VSS: ((E F) (G H))
VSS: ((E F G H))
USS: ((G H))
VSS: ((G H))
((A B C D) (A B E F) (A B G H) (C D E F) (C D G H) (E F G H) (A B C D E F)
 (A B C D G H) (E F G H) (A B C D E F G H) (C D E F) (C D G H) (E F G H)
 (C D E F G H) (E F G H))

lists vss combiner combiner /code>,并且由于其中许多列表具有相同的尾巴,因此在结果中发生了重复。 花式组合者函数使用 remove-duplicates 在结果中的每个列表中准备'& 符号之前,请删除这些重复。

结果

CL-USER> (fancy-combiner '((a b) (c d)))
((& A B C D))

CL-USER> (fancy-combiner '((a b) (c d) (e f)))
((& A B C D) (& A B E F) (& A B C D E F) (& C D E F))

CL-USER> (fancy-combiner '((a b) (c d) (e f) (g h)))
((& A B C D) (& A B E F) (& A B G H) (& A B C D E F) (& A B C D G H)
 (& A B C D E F G H) (& C D E F) (& C D G H) (& C D E F G H) (& E F G H))

这些并不是问题和评论中OP指示的结果,但是由于OP评论中似乎存在不一致之处,因此很难确切地知道预期的内容。

我必须写一个额外的功能吗?

假设该解决方案确实符合OP期望,则您可以通过使用lambda表达式代替 fancy-transform 将整个内容写入一个函数,然后将调用替换为组合 fancy-combiner 带有等效循环表达式。这对此没有任何好处,因此所产生的代码将不清楚。

OP问:“ 是否有一种循环变量使用临时结果? ,通过将(ABCD)插入到输入遍历期间的某个时候。这是不可能的。 被禁止破坏性地修改在traversal a traversal a thraversal 列表中操作。循环设施没有为此提供任何机制。

The Problem Statement

The OP requirements are murky. Given an input list it isn't entirely clear what the output should be; this is compounded by inconsistencies in the example outputs provided by OP in the question and comments.

OP starts from a loop that combines the elements of an input list:

(loop for (x . tail) on l1
      append (loop for y in tail
                   collect (append (list '&)  x y)))

This loop will not produce pairs of the sort shown in OP expected output:

((a b) (c d)) -> ((& a b ) (& c d) (& a b c d))

Instead, the output of the above is:

((a b) (c d)) -> ((& a b c d))

The final result of operating on ((a b) (c d) (e f)) appears to be ((& a b e f) (& c d e f) (& a b c d e f)). But this seems to be missing the list (& a b c d).

In the comments is appears that the result of operating on the list ((a b) (c d) (e f) (g h)) should be ((& a b) (& c d) (& a b c d) (& a b e f) (& c d e f) (& a b c d e f) (& a b g h) (& c d g h) (& a b c d g h) (& a b e f g h) (& c d e f g h) (& a b c d e f g h)). This result includes the lists (& a b) and (& c d), which don't seem to have any connection to the original operation. Further, (& e f) and (& g h) are mysteriously absent in this result.

From this, though, it seems that the OP desires to collect a result containing all of the original combinations generated by the first operation together with the result of operating on a series of lists reduced by cdr and transformed by concatenating the first pair of each list.

A Possible Solution

I don't claim that this is an optimal solution, a particularly good solution, or that it even solves OP's problem as it is not very clearly laid out here. I only claim that this may be a solution which uses OP's original combining operation and that is reasonably clear. I suspect that a better solution might be found by rethinking the problem from the beginning.

The OP operation can be placed in a function:

(defun combiner (xss)
  (loop for (x . tail) on xss
        append (loop for y in tail
                     collect (append x y))))

Here the added symbol '& is ignored; that will only confuse matters while we are combining list elements, and a symbol can easily be prepended to the result lists when we are done.

There is no need to use combiner to operate on the first two elements of a list since the result is always just the concatenation of those two list elements. It would be useful to write a function that transforms a list by concatenating the first two elements. Singleton lists should be transformed to nil:

(defun fancy-transform (xss)
  (unless (null (cdr xss))
    (cons (append (first xss) (second xss))
          (cddr xss))))

Now we are ready to write a function that uses combiner to create the desired result:

(defun fancy-combiner (xss)
  (mapcar (lambda (xs) (cons '& xs))
          (remove-duplicates
           (loop for uss on xss
                 append (loop for vss on uss by #'fancy-transform
                              append (combiner vss)))
           :test #'equal)))

The action is in the loop macro here. The call to remove-duplicates is needed since the result of the loop contains duplicates, and the call to mapcar is used to prepend '& symbols to each list in the result.

The outer loop feeds progressively smaller versions of the input list to the inner loop; each of these lists is transformed by combiner, then reduced by fancy-transform, which reduces the list by appending the first two elements or returning nil when a singleton list is reached (ending that iteration).

It may help to see the progress as an input list is processed. This fancy-combiner-illustrated function does not remove duplicates or prepend a symbol to the lists in the result:

(defun fancy-combiner-illustrated (xss)
  (loop for uss on xss
        do (format t "~%USS: ~A" uss)
        append (loop for vss on uss by #'fancy-transform
                     do (format t "~%VSS: ~A" vss)
                     append (combiner vss))))
CL-USER> (fancy-combiner-illustrated '((a b) (c d) (e f) (g h)))

USS: ((A B) (C D) (E F) (G H))
VSS: ((A B) (C D) (E F) (G H))
VSS: ((A B C D) (E F) (G H))
VSS: ((A B C D E F) (G H))
VSS: ((A B C D E F G H))
USS: ((C D) (E F) (G H))
VSS: ((C D) (E F) (G H))
VSS: ((C D E F) (G H))
VSS: ((C D E F G H))
USS: ((E F) (G H))
VSS: ((E F) (G H))
VSS: ((E F G H))
USS: ((G H))
VSS: ((G H))
((A B C D) (A B E F) (A B G H) (C D E F) (C D G H) (E F G H) (A B C D E F)
 (A B C D G H) (E F G H) (A B C D E F G H) (C D E F) (C D G H) (E F G H)
 (C D E F G H) (E F G H))

The lists VSS are the ones operated on by combiner, and since many of these list have tails that are the same, duplicates occur in the result. The fancy-combiner function uses remove-duplicates to remove these duplicates before prepending the '& symbol to each list in the result.

Results

CL-USER> (fancy-combiner '((a b) (c d)))
((& A B C D))

CL-USER> (fancy-combiner '((a b) (c d) (e f)))
((& A B C D) (& A B E F) (& A B C D E F) (& C D E F))

CL-USER> (fancy-combiner '((a b) (c d) (e f) (g h)))
((& A B C D) (& A B E F) (& A B G H) (& A B C D E F) (& A B C D G H)
 (& A B C D E F G H) (& C D E F) (& C D G H) (& C D E F G H) (& E F G H))

These aren't exactly the results indicated by OP in the question and comments, but since there seem to be inconsistencies in OP comments it is hard to know exactly what is expected.

Would I Have to Write an Extra Function?

Assuming the this solution does match OP expectations, you could write the whole thing as one function by using a lambda expression in place of fancy-transform and replacing the call to combiner in fancy-combiner with the equivalent loop expression. There is no benefit to that, and the resulting code would be less clear.

OP asks: "is there a kind of loop variable to use a provisional result?", but it seems that OP desires to change the input list as it is processed, e.g., by inserting (a b c d) into the input list at some point during the traversal of the input. This is not possible in Common Lisp; it is forbidden to destructively modify any list during a traversal operation. The loop facility does not provide any mechanism for this.

鸢与 2025-02-04 08:08:03

我开始在没有互联网的火车上解决这个问题。
因此,当我到达时,另一个答案就在那里。
但是尽管如此,我会发布我的构造。

((a b) (c d) (e f) (g h))
;; => ((a b) (c d) (e f) (g h)
;;     (a b c d) (a b e f) (c d e f) (a b g h) (c d g h)
;;     (a b c d e f) (a b c d g h) 
;;     (a b e f g h) 
;;     (c d e f g h) 
;;     (a b c d e f g h))

第一行是列表。
第二行是该列表元素的配对 - 但仅与零件
上一个元素的CDR
第三到前排是与第二行和列表的 cdr 配对。
最后一行是一切的统一。

(defun once-flatten (lol)
  (loop for x in lol
        if (atom x)
          collect x
        else
          append x))
        
(defun list-and-pairings* (list) ;; or #'append
  (append list
          (mapcar #'once-flatten
                  (loop for (x . tail) on list
                        append (loop for y in (if (> (length tail) 1)
                                                  (list-and-pairings* tail)
                                                  tail)
                                     collect (list x y))))))

(defun add-& (lol) (mapcar (lambda (x) (if (atom x) x (cons '& x))) lol))

然后我们可以做:

(add-& (list-and-pairings* '((a b) (c d) (e f) (g h))))
;; => ((& A B) (& C D) (& E F) (& G H) 
;;     (& A B C D) (& A B E F) (& A B G H)
;;     (& A B C D E F) (& A B C D G H) (& A B C D E F G H) (& A B E F G H)
;;     (& C D E F) (& C D G H) (& C D E F G H) (& E F G H))

一个人也可以使用:

(defun add-& (lol)
 (loop for x in lol
       if (atom x)
         collect x
       else
         collect (cons '& x)))

I started to solve this during a train ride where I had no internet.
So when I arrived the other answer was there.
But nevertheless, I will post my construct.

((a b) (c d) (e f) (g h))
;; => ((a b) (c d) (e f) (g h)
;;     (a b c d) (a b e f) (c d e f) (a b g h) (c d g h)
;;     (a b c d e f) (a b c d g h) 
;;     (a b e f g h) 
;;     (c d e f g h) 
;;     (a b c d e f g h))

The first row is the list as it is.
The second row is pairings of the elements of this list - but only with the parts
cdr of the last element.
The third to before-last row is pairings with the second row and the cdr of the list.
And the last row is unification of everything.

(defun once-flatten (lol)
  (loop for x in lol
        if (atom x)
          collect x
        else
          append x))
        
(defun list-and-pairings* (list) ;; or #'append
  (append list
          (mapcar #'once-flatten
                  (loop for (x . tail) on list
                        append (loop for y in (if (> (length tail) 1)
                                                  (list-and-pairings* tail)
                                                  tail)
                                     collect (list x y))))))

(defun add-& (lol) (mapcar (lambda (x) (if (atom x) x (cons '& x))) lol))

And then we can do:

(add-& (list-and-pairings* '((a b) (c d) (e f) (g h))))
;; => ((& A B) (& C D) (& E F) (& G H) 
;;     (& A B C D) (& A B E F) (& A B G H)
;;     (& A B C D E F) (& A B C D G H) (& A B C D E F G H) (& A B E F G H)
;;     (& C D E F) (& C D G H) (& C D E F G H) (& E F G H))

One can also use:

(defun add-& (lol)
 (loop for x in lol
       if (atom x)
         collect x
       else
         collect (cons '& x)))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文