3

所以在这里我有几个我想使用的已定义列表:

(DEFINE list0 (LIST 'j 'k 'l 'm 'n 'o 'j) )
(DEFINE list1 (LIST 'a 'b 'c 'd 'e 'f 'g) )
(DEFINE list2 (LIST 's 't 'u 'v 'w 'x 'y 'z) )
(DEFINE list3 (LIST 'j 'k 'l 'm 'l 'k 'j) )
(DEFINE list4 (LIST 'n 'o 'p 'q 'q 'p 'o 'n) )
(DEFINE list5 '( (a b) c (d e d) c (a b) ) )
(DEFINE list6 '( (h i) (j k) l (m n) ) )
(DEFINE list7 (f (a b) c (d e d) (b a) f) )

我想做的是为“中间”函数创建一个递归函数,它可以这样做:

MIDDLE: (middle 1st) 应该返回一个仅由 1st 的中间元素组成的单元素列表 [或者如果 1st 中有偶数个元素,则返回空列表]。那是,

(middle '(a b c d e f g) ) 应该/将返回: (d)

(middle '(s t u v w x y z) ) 应该/将返回空字符串。

(middle '( (a b) c (d e d) c (b a) ) ) 应该/将返回: ( (d e d) ) 请注意,这( (d e d) )是一个包含中间事物的列表,它本身就是一个列表。

我认为我必须把它分成两个问题。首先是我需要一个可以选择列表第 n 项的函数。我对创建它知之甚少。其次,您需要一个函数来确定中间项的位置以及是否存在中间项。(我对如何创建它也知之甚少。然后

(define middle
    (lambda (L)
        (if (middle? L)
        (nth-term (middle L) L)
        '())))

这是我的 evens 函数,我想知道是否有更简单的方法来解决它:

(define evens
    (lambda (L)
    (if (or (NULL? (cddr L)))
        '()
    (cons (cadr L) (evens (cddr L))))))
4

3 回答 3

3

最简单的方法是使用 length 函数来获取列表的长度,然后确保长度不是偶数(如果是,则返回一个空列表)。一旦我们知道长度是奇数,返回列表中一半长度减去 1 的元素。结果是列表的中间。以下是代码的实际样子:

    (define (middle lis)
      (let ((list-length (length lis)))
        (if (even? list-length)
            '()
            (list (list-ref lis (/ (- list-length 1) 2))))))

要回答主题行中的问题,您可以使用 list-ref 过程获得列表的第 n 项,如下所示:

    > (list-ref '(a b c d) 2)
    'c

如果您仍然对任何事情感到困惑,请告诉我,我会尽力澄清。

于 2012-11-14T04:33:15.813 回答
2

答案可以稍微改进如下:

(define (middle lst)
  (let ((len (length lst)))
    (if (even? len)
        '()
        (list (list-ref lst (quotient len 2))))))

请注意,有一种更简单的方法可以获取中间元素的索引。

于 2012-11-14T11:53:18.550 回答
2

显而易见的方法(计算长度;除以二;在列表中查找)需要两次遍历列表。

这是一种只需要一次通过的替代方法:

(define (middle lst)
  (letrec
    ((middle-odd
       (lambda (x y) (if (null? x) (list (car y)) (middle-even (cdr x) (cdr y)))))
     (middle-even
       (lambda (x y) (if (null? x) '() (middle-odd (cdr x) y)))))
    (middle-even lst lst)))
于 2012-11-14T12:34:33.837 回答