scheme删除列表中除最后一个元素之外的所有重复元素

时间:2017-05-02 18:22:03

标签: scheme

我正在学习方案,作为一项任务,我已经完成了一系列功能,如反转列表或连接它们;所有递归并且不使用追加或反向内置的。

我的作业是编写一个函数,它只接收一个列表的参数,并返回除最后一个之外所有重复元素都消失的其他列表。我可以使用辅助功能。

我的想法是将看到的元素累积到由辅助递归函数托管的累加器中。作为基本casa,如果列表为null,则连接第一个元素并将其保存在累加器上;如果没有,取第一个元素并将其保存在辅助元素上,但删除所有元素并构成一个新列表,之前已插入原始的第一个列表元素:

连接到列表

    (define (concatena L1 L2)
    (cond
        ((null? L1) L2)
        (else (cons (car L1) (concatena (cdr L1) L2)))
    )
)

消除列表L2中的所有L1元素

(define (elimina L1 L2)
    (cond ((empty? L2) L2)
          ( (equal? (car L2) L1) (elimina L1 (cdr L2) ) )
          (else (concatena (list (car L2) ) (elimina L1 (cdr L2) ) ) )
    )
)

我的方法:

(define (repetidos L1)
    repetidos-recorre(L1 '())
)
(define (repetidos-recorre(L1 acc))
    (if (null? (cdr L1))
        ( concatena( list(car L1) acc ) )   
        ( concatena ( ( car L1 ) ( cons( elimina( list( ( car L1 ) acc ) ) ) ) ) ) 
    )
)

当我意识到我应该用某种方式来知道实际解析的元素是否已经存在于累积的元素上时我开发了函数:

(define (miembro L X)
    (if (null? L)
        #f
        (if (eq? (car L) X)
            #t
            (miembro (cdr L) X)
        )
    )
)

我大致尝试过:

(define (repetidos L)
    (repetidos-recorre L '()
    )
)
(define (repetidos-recorre L acumulado)
    (if (null? L)
        acumulado
        (if (miembro acumulado (car L) )
            ( repetidos-recorre (cdr L) (concatena ( elimina (car L) acumulado ) (car L)   )   ) )
            (repetidos-recorre (cdr L) (concatena (car L) acumulado))
    )
)

我结束了我被卡住的一点,因为我知道这段代码是错误的,因为我还没有测试过这两个重复功能。我知道所有辅助设备都能正常运行,我理解它们但是我需要帮助来解决最后一项任务,或者至少有人说我如何解决这个问题。谢谢你的时间!

1 个答案:

答案 0 :(得分:0)

假设miembro已正确实施,您不需要使用eliminaconcatena。更好的方法是:

(define (repetidos L)
  (repetidos-recorre L '()))

(define (repetidos-recorre L acumulado)
  (if (null? L)
      acumulado
      (if (miembro acumulado (car L))
          (repetidos-recorre (cdr L) acumulado)
          (repetidos-recorre (cdr L) (cons (car L) acumulado)))))

此外,不是嵌套if,而是使用单个cond,但我现在暂时保留原样。这是它的工作原理:

(repetidos '(1 a a 2 a))
=> '(2 a 1)
(repetidos '(1 a 2 a))
=> '(2 a 1)
(repetidos '(1 2 a))
=> (repetidos '(1 2 a))

请注意,元素以相反的顺序显示,因为我们在列表的头部重新cons元素。如果订单很重要,那么我们必须使用concatena,但请记住,它是一个效率较低的解决方案:

(define (repetidos-recorre L acumulado)
  (if (null? L)
      acumulado
      (if (miembro acumulado (car L))
          (repetidos-recorre (cdr L) acumulado)
          (repetidos-recorre (cdr L) (concatena acumulado (list (car L)))))))

如您所见,订单已保留:

(repetidos '(1 a a 2 a))
=> '(1 a 2)
(repetidos '(1 a 2 a))
=> '(1 a 2)
(repetidos '(1 2 a))
=> '(1 2 a)