在不使用驱动程序功能的情况下使用单个功能在列表中查找最小和最大数字?
Using a single function to find min and max numbers in a list without using a driver function?
我目前对一般的函数式编程背后的想法感到困惑。我目前有一个解决我的问题的可行方法(即找到列表的最小值和最大值,并将它们返回到新列表中)但是要做到这一点,我的解决方案基本上需要 3 个函数,这让我很困扰,因为我确定有一种方法可以只用方案中的 1 个函数来完成。
所以..我的问题是,如何将 2 个函数的输出组合成 1 个简洁的函数? (驱动函数)
这是我的...
(define (findMax lst) ; Find and return maximum number in a list
(cond [(null? lst) '()]
[(= (length lst) 1) (list-ref lst 0)]
[(> (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMax (drop-right lst 1))]
[(< (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMax (cdr lst))]
(else
(findMax (cdr lst))
)
)
)
(define (findMin lst) ; Find and return smallest number in a list
(cond [(null? lst) '()]
[(= (length lst) 1) (list-ref lst 0)]
[(> (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMin (cdr lst))]
[(< (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMin (drop-right lst 1))]
(else
(findMin (cdr lst))
)
)
)
我使用一个驱动程序函数来获取这两个函数,并在此处显示一个新列表:
(define (findEnds lst)
(list (findMin lst) (findMax lst))
)
基本上,如果给定一个列表:
(6 7 8 4 9 2)
输出将是:
(2 9)
我知道有一些方法可以使用 lambda 在一个函数中完成所有这些,但我需要指出正确的方向。谢谢!
这是我的版本(请注意,我已将其更改为 return 结果作为单个点对,而不是包含两个元素的列表 †):
(define (min/max lst)
(if (empty? lst)
#f
(let ((next (min/max (cdr lst))))
(define cur (car lst))
(if (not next)
(cons cur cur)
(cons (min (car next) cur) (max (cdr next) cur))))))
示例:
> (min/max '(3 1 4 1 5 9))
(1 . 9)
† 如果你真的想使用两个元素的列表,把所有的cons
改成list
,把(cdr next)
改成(cadr next)
。
这实际上是一个非常好的挑战,可能有助于学习一些 Scheme 概念。我已经使用 fold-left. It might also be fun using a named-let
实现了 min/max
(define (min/max lst)
(fold-left
(lambda (acc num)
(cons (min num (car acc)) (max num (cdr acc))))
(cons +inf.0 -inf.0)
lst))
我目前对一般的函数式编程背后的想法感到困惑。我目前有一个解决我的问题的可行方法(即找到列表的最小值和最大值,并将它们返回到新列表中)但是要做到这一点,我的解决方案基本上需要 3 个函数,这让我很困扰,因为我确定有一种方法可以只用方案中的 1 个函数来完成。
所以..我的问题是,如何将 2 个函数的输出组合成 1 个简洁的函数? (驱动函数)
这是我的...
(define (findMax lst) ; Find and return maximum number in a list
(cond [(null? lst) '()]
[(= (length lst) 1) (list-ref lst 0)]
[(> (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMax (drop-right lst 1))]
[(< (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMax (cdr lst))]
(else
(findMax (cdr lst))
)
)
)
(define (findMin lst) ; Find and return smallest number in a list
(cond [(null? lst) '()]
[(= (length lst) 1) (list-ref lst 0)]
[(> (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMin (cdr lst))]
[(< (list-ref lst 0) (list-ref lst (- (length lst) 1))) (findMin (drop-right lst 1))]
(else
(findMin (cdr lst))
)
)
)
我使用一个驱动程序函数来获取这两个函数,并在此处显示一个新列表:
(define (findEnds lst)
(list (findMin lst) (findMax lst))
)
基本上,如果给定一个列表:
(6 7 8 4 9 2)
输出将是:
(2 9)
我知道有一些方法可以使用 lambda 在一个函数中完成所有这些,但我需要指出正确的方向。谢谢!
这是我的版本(请注意,我已将其更改为 return 结果作为单个点对,而不是包含两个元素的列表 †):
(define (min/max lst)
(if (empty? lst)
#f
(let ((next (min/max (cdr lst))))
(define cur (car lst))
(if (not next)
(cons cur cur)
(cons (min (car next) cur) (max (cdr next) cur))))))
示例:
> (min/max '(3 1 4 1 5 9))
(1 . 9)
† 如果你真的想使用两个元素的列表,把所有的cons
改成list
,把(cdr next)
改成(cadr next)
。
这实际上是一个非常好的挑战,可能有助于学习一些 Scheme 概念。我已经使用 fold-left. It might also be fun using a named-let
实现了min/max
(define (min/max lst)
(fold-left
(lambda (acc num)
(cons (min num (car acc)) (max num (cdr acc))))
(cons +inf.0 -inf.0)
lst))