2016-11-09 102 views
1

当这样写的错误说:后4个部分,如果:如何使用球拍/方案建立滚动窗口程序?

(define (rolling-window l size) 
    (if (< (length l) size) l 
    (take l size) (rolling-window (cdr l) size))) 

,当有另一个paranthesis,使其3个部分:

(define (rolling-window l size) 
    (if (< (length l) size) l 
    ((take l size) (rolling-window (cdr l) size)))) 

然后它说:应用程序:不是一个程序;

+0

https://docs.racket-lang.org/reference/if.html – coredump

+1

使用'cond'。或者,用'begin'或'let'封装分支,但使用'cond'可能更容易。 –

+0

(取l尺寸)(滚动窗口(cdr l)尺寸) 应该在else部分不需要第三个替代方案 – X10D

回答

3

如何在if/else中写入多个表达式在球拍/方案中?

那么这不是真正的问题。问题是“如何使用球拍建立滚动窗口程序?”。无论如何,看起来你可能来自另一种编程语言。处理链表首先可能有点棘手。但请记住,要计算列表的长度,您必须遍历整个列表。所以在这里使用length是一个反模式。

相反,我会建议您在rolling-window过程中创建一个aux iliary过程,在遍历列表时构建窗口。这样您就不必浪费迭代计算列表中的元素。

然后,如果您的aux过程返回并且为空窗口,那么您知道您已完成计算给定输入列表的窗口。

(define (rolling-window n xs) 
    (define (aux n xs) 
    (let aux-loop ([n n] [xs xs] [k identity]) 
     (cond [(= n 0) (k empty)] ;; done building sublist, return sublist 
      [(empty? xs) empty] ;; reached end of xs before n = 0, return empty window 
      [else (aux-loop (sub1 n) (cdr xs) (λ (rest) (k (cons (car xs) rest))))]))) ;; continue building sublist 

    (let loop ([xs xs] [window (aux n xs)] [k identity]) 
    (cond ([empty? window] (k empty)) ;; empty window, done 
      ([empty? xs] (k empty))  ;; empty input list, done 
      (else (loop (cdr xs) (aux n (cdr xs)) (λ (rest) (k (cons window rest)))))))) ;; continue building sublists 

(rolling-window 3 '(1 2 3 4 5 6)) 
;; => '((1 2 3) (2 3 4) (3 4 5) (4 5 6)) 

它适用于空窗

(rolling-window 0 '(1 2 3 4 5 6)) 
;; => '() 

而空列表太

(rolling-window 3 '()) 
;; => '() 
+0

一个非常好的解决方案。一个小小的评论:因为循环不会修改'n',所以它可以被排除在参数列表之外。 – soegaard

+0

@soegaard谢谢你的支持! – naomik

+0

xs的词源是什么? – X10D

2

这里是一个另类:

#lang racket 

(define (rolling-window n xs) 
    (define v (list->vector xs)) 
    (define m (vector-length v)) 
    (for/list ([i (max 0 (- m n -1))]) 
    (vector->list (vector-copy v i (+ i n))))) 

(rolling-window 3 '(a b c d e f g)) 
(rolling-window 3 '()) 
(rolling-window 0 '(a b c)) 

输出:

'((a b c) (b c d) (c d e) (d e f) (e f g)) 
'() 
'(()()()()) ; lack of spec makes this ok ! 
1

下面对OP功能的修改进行了修改。它包括一个outlist,初始默认为空列表。子列表被添加到此列表中,直到(length l)小于size

(define (rolling-window l size (ol '())) 
    (if (< (length l) size) (reverse ol) 
     (rolling-window (cdr l) size (cons (take l size) ol)))) 

测试:

(rolling-window '(1 2 3 4 5 6) 2) 
(rolling-window '(1 2 3 4 5 6) 3) 
(rolling-window '(1 2 3 4 5 6) 4) 

输出:

'((1 2) (2 3) (3 4) (4 5) (5 6)) 
'((1 2 3) (2 3 4) (3 4 5) (4 5 6)) 
'((1 2 3 4) (2 3 4 5) (3 4 5 6)) 
0

在这一个任何改进?

(define (rolling-window l size) 
    (cond ((eq? l '()) '()) 
     ((< (length l) size) '()) 
     ((cons (take l size) (rolling-window (cdr l) size))))) 
+0

我已经告诉过你'长度'是一个反模式 – naomik

+0

1:这将是很好的摆脱长度检查。用任何方式组合take函数,以便在列表不够长的时候静静地退出,而不是抛出列表太短的错误? 2:是的,它效率较低,但可读性更强一点? – X10D