给定一个数字列表,比如(1 3 6 10 0)
,如何计算差异(x i - x i-1 ),前提是你有x -1 = 0?
(此示例中的结果应为(1 2 3 4 -10)
)
我发现这个解决方案是正确的:
(define (pairwise-2 f init l) (first (foldl (λ (x acc-data) (let ([result-list (first acc-data)] [prev-x (second acc-data)]) (list (append result-list (list(f x prev-x))) x))) (list empty 0) l))) (pairwise-2 - 0 '(1 3 6 10 0)) ;; => (1 2 3 4 -10)
然而,我认为应该有更优雅但同样灵活的解决方案。这太丑了。
我是函数式编程的新手,希望听到有关代码的任何建议。
感谢。
答案 0 :(得分:2)
map
需要多个参数。所以我会做的
(define (butlast l)
(reverse (cdr (reverse l))))
(let ((l '(0 1 3 6 10)))
(map - l (cons 0 (butlast l)))
如果你想把它包装在一个函数中,比如说
(define (pairwise-call f init l)
(map f l (cons init (butlast l))))
这当然是不是 Little Schemer Way,而是避免自己编写递归的方式。选择你最喜欢的方式。
答案 1 :(得分:1)
我没有在狗的年代做过计划,但这让我觉得这是一个典型的小型lisper型问题。
我从一个基本定义开始(请忽略parens错位 - 我没有方便的解释器:
(define pairwise-diff
(lambda (list)
(cond
((null? list) '())
((atom? list) list)
(t (pairwise-helper 0 list)))))
它处理null和atom的垃圾案例,然后将meat case委托给一个帮助者:
(define pairwise-helper
(lambda (n list)
(cond
((null? list) '())
(t
(let ([one (car list)])
(cons (- one n) (pairwise-helper one (cdr list))))
))))
您可以使用“if”重写此内容,但我很难使用cond。
这里有两种情况:空列表 - 这很容易,其他一切。 对于其他一切,我抓住列表的头部并将这个差异归结为递归案例。我认为它不会变得简单得多。
答案 2 :(得分:1)
在完善并适应PLT计划plinth的code之后,我认为几乎完美的解决方案将是:
(define (pairwise-apply f l0 l) (if (empty? l) '() (let ([l1 (first l)]) (cons (f l1 l0) (pairwise-apply f l1 (rest l))))))
答案 3 :(得分:1)
Haskell告诉我使用zip
;)
(define (zip-with f xs ys)
(cond ((or (null? xs) (null? ys)) null)
(else (cons (f (car xs) (car ys))
(zip-with f (cdr xs) (cdr ys))))))
(define (pairwise-diff lst) (zip-with - (cdr lst) lst))
(pairwise-diff (list 1 3 6 10 0))
; gives (2 3 4 -10)
答案 4 :(得分:1)
无论如何,一旦最短的参数列表用完就不会完成映射吗?
(define (pairwise-call fun init-element lst) (map fun lst (cons init-element lst)))
编辑:jleedev告诉我在至少一个Scheme实现中不是这种情况。这有点烦人,因为没有O(1)操作来切断列表的末尾。
也许我们可以使用reduce
:
(define (pairwise-call fun init-element lst) (reverse (cdr (reduce (lambda (a b) (append (list b (- b (car a))) (cdr a))) (cons (list init-element) lst)))))
(免责声明:快速入侵,未经测试)
答案 5 :(得分:0)
这是最简单的方法:
(define (solution ls)
(let loop ((ls (cons 0 ls)))
(let ((x (cadr ls)) (x_1 (car ls)))
(if (null? (cddr ls)) (list (- x x_1))
(cons (- x x_1) (loop (cdr ls)))))))
(display (equal? (solution '(1)) '(1))) (newline)
(display (equal? (solution '(1 5)) '(1 4))) (newline)
(display (equal? (solution '(1 3 6 10 0)) '(1 2 3 4 -10))) (newline)
写出每个示例的代码扩展,看看它是如何工作的。
如果您有兴趣开始使用FP,请务必查看如何设计程序。当然它是为人们编写的全新的,但它有很多优秀的FP成语。
答案 6 :(得分:0)
(define (f l res cur)
(if (null? l)
res
(let ((next (car l)))
(f (cdr l) (cons (- next cur) res) next))))
(define (do-work l)
(reverse (f l '() 0)))
(do-work '(1 3 6 10 0))
==> (1 2 3 4 -10)