【问题标题】:how can i append to a list without creating a dotted pair如何在不创建点对的情况下附加到列表
【发布时间】:2017-11-26 11:54:56
【问题描述】:

如何将(1 2 3) 附加到() 的末尾以生成((1 2 3))
我如何将(4 5 6) 附加到 that 的末尾以生成((1 2 3) (4 5 6))
我如何将"|" 附加到 that 的末尾以使((1 2 3) (4 5 6) "|")

没有点对。

我正在与 Chicken Scheme 合作,但此时我会从任何方案中得到答案。请注意,这些列表中的任何一个也可以是谁知道什么的嵌套列表......我只是在写一个简单的例子。

注意:@sjamaan 展示了 a 使用 append 的解决方案,该解决方案涉及将所有内容包装在另一个列表中,以弥补名称之外的附加操作。

(append (list 1 2 3) "|" ) ;=> (1 2 3 . "|") ;^^ didn't actually append, created a dotted pair (append '(1 2 3) (list 4 5 6)) ;=> (1 2 3 4 5 6) ; don't want unwrapped list ;^^ didn't actually append the list i gave it but appended the contents of the list.

基本上,我希望有一个 append 方法,它实际上是附加你给它的东西,而不是附加它的内容,或者接受它并形成一个点对。也许我只是一个梦想家......我可以编写一个“没有真正附加”的方法,它只需要你给它的任何参数并将它们包装在一个外部列表中以进行补偿,但这只是愚蠢......当然方案有一些方法可以没有这种疯狂的追加。

【问题讨论】:

  • @jcolemang 它相似但不一样。另一个问题相当模棱两可,并没有涵盖相同的领域。它及其答案未能解决附加列表不是附加列表而是附加内容的事实,并且没有解决附加单个项目的问题。

标签: scheme chicken-scheme


【解决方案1】:

下面是追加的方法:

(define (append2 lst1 lst2)
  (if (null? lst1)
      lst2                               ; the second list is unaltered
      (cons (car lst1)
            (append2 (cdr lst1) lst2))))

创建一个由lst1lst2 中的所有元素组成的对链。它不会在lst2 中不存在的情况下配对,所以:

(append2 '(1 2 3) '(4 5)) ; ==> (1 2 3 4 5)
(append2 '(1 2 3) '())    ; ==> (1 2 3) and not (1 2 3 ())
(append2 '(1 2 3) '5)     ; ==> (1 2 3 . 5)

请注意,像(1 2 3) 这样的每个列表实际上都是(1 2 3 . ()),或者更准确地说是(1 . (2 . (3 . ())))

我如何将(1 2 3) 附加到() 的末尾以生成((1 2 3))

(define (insert-last e lst)
  (let helper ((lst lst))
    (if (pair? lst)
        (cons (car lst)
              (helper (cdr lst)))
        (cons e '()))))

(insert-last '(1 2 3) '())                    
; ==> ((1 2 3))

我如何将(4 5 6) 附加到 that 的末尾以生成((1 2 3) (4 5 6))

(insert-last '(4 5 6) '((1 2 3)))  
; ==> ((1 2 3) (4 5 6))

我如何将"|" 附加到 that 的末尾以生成((1 2 3) (4 5 6) "|")

(insert-last "|" '((1 2 3) (4 5 6)))  
; ==> ((1 2 3) (4 5 6) "|")

知道这很像append。这些是制作该列表的最糟糕的方法,因为您每次都在制作新列表。每个插入的 O(n) 和 n 个元素的 O(n^2)。如果您可以以相反的顺序执行此操作,您将得到执行此操作的 O(1) 而不是每个插入操作的 O(n)。你用cons代替insert-last

(cons '"|" '())               ; ==> ("|")
(cons '(4 5 6) '("|"))        ; ==> ((4 5 6) "|")
(cons '(1 2 3) '((4 5 6) "|") ; ==> ((1 2 3) (4 5 6) "|")

对于处理的 n 个元素,这是 O(1),O(n)。如果你需要按照你可以累积的原始顺序来做,然后倒过来..

(cons '(1 2 3) '())                ; ==> ((1 2 3))
(cons '(4 5 6) '((1 2 3)))         ; ==> ((4 5 6) (1 2 3))
(cons '"|" '((4 5 6) (1 2 3)))   ; ==> ("|" (4 5 6) (1 2 3))
(reverse '("|" (4 5 6) (1 2 3))  ; ==> ((1 2 3) (4 5 6) "|")

这是 O(1),然后是 O(n),但它仍然是 O(1) 摊销。 O(n) 对于您处理的 n 元素。

【讨论】:

  • 感谢您花时间和精力回答这个问题。我会注意到附加的 "|" 答案并不完全正确,但你肯定回答了问题的核心。
  • 我听说insert-last 之前叫snoc,顺便说一句。
【解决方案2】:

append 不会将原子附加到列表中。它连接列表。在串联有意义之前,您必须将原子提升到列表中。

(append xs (list y))

但是指出(reverse (cons y (reverse xs))) 具有相同的结果是有意义的。 reverse 建议如果您需要将原子附加到末尾,您可能会向后构建您的列表。

【讨论】:

    【解决方案3】:

    不出所料,您要查找的过程称为append(来自 SRFI-1)。它将事物列表附加到另一个列表中。这确实意味着,如果您只想添加一项,则需要从中列出一个列表:

    (append '() '((1 2 3))) => ((1 2 3))
    (append '((1 2 3)) '((4 5 6))) => ((1 2 3) (4 5 6))
    (append '((1 2 3) (4 5 6)) '("|") ) => ((1 2 3) (4 5 6) "|")
    

    它接受多个参数,它们都将按顺序附加到彼此,所以你也可以这样做:

    (append '() '((1 2 3)) '((4 5 6)) '("|")) => ((1 2 3) (4 5 6) "|")
    

    希望这会有所帮助!

    【讨论】:

    • 我明白你在做什么,但它并不完全相同。不同之处在于,您通过将所有内容包装在另一个列表中来解决附加的愚蠢问题。添加一个列表或另一个列表的项目类似于(map (labmda(x)(append destination-list (list x)) source-list)。我希望有一个解决方案不是“嘿,将所有内容嵌套在另一个列表中,因为 append 很愚蠢,然后再做。”没有更直接的版本吗?
    • 真正的答案是将所有内容都包含在一个列表中。原因是 append 已经 has 重建除了最后一个列表(包含原子)之外的所有列表的列表单元结构。对于列表,偶尔这样做很有意义,但在末尾不断添加原子效率极低,因此为此专门设置一个程序是没有意义的。因此,如果您正在这样做,请查看@dan-d 的建议以维护反向列表,不断将缺点放在前面并在最后反转一次。这是 Scheme 中的典型使用模式。
    • 或者,您可以保留列表中的最后一个 cdr 并调用set-cdr!(再次)使用仅包含原子的列表。我只建议在性能关键代码中执行此操作,因为它会掩盖您的算法,并且如果传入列表,它会与调用者的数据混淆。请注意,这是在 C 或其他命令式语言中使用单链表执行此操作的典型方式。
    • 谢谢。我接受@Sylwester 作为答案,因为它对人们最有用,但我真的很感谢额外的解释。
    • 我同意,@Sylwester 的回复是最彻底的。
    【解决方案4】:

    无论您是否愿意,都会创建 cons 单元格,因为列表由 cons 单元格组成。

    如何将 (1 2 3) 附加到 () 的末尾以生成 ((1 2 3))

    CL-USER 24 > (list '(1 2 3))
    ((1 2 3))
    

    我如何将 (4 5 6) 添加到末尾以生成 ((1 2 3) (4 5 6))

    CL-USER 25 > (append '((1 2 3)) (list '(4 5 6)))
    ((1 2 3) (4 5 6))
    

    如何添加“|”到最后使 ((1 2 3) (4 5 6) "|")

    CL-USER 26 > (append '((1 2 3) (4 5 6)) (list "|"))
    ((1 2 3) (4 5 6) "|")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-24
      • 1970-01-01
      • 1970-01-01
      • 2012-12-01
      • 2014-11-15
      • 2019-08-27
      • 2015-03-17
      • 1970-01-01
      相关资源
      最近更新 更多