2016-11-09 4 views
1

Wenn auf diese Weise geschrieben der Fehler sagt: 4 Teile nach, wenn:Wie erstellt man ein Rolling-Window-Verfahren mit Schläger/Schema?

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

und wenn ein anderer geklam- mert es gibt es drei Teile zu machen:

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

dann heißt es: Anwendung: kein Verfahren;

+0

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

+1

Verwenden Sie 'cond'. Wickeln Sie den Zweig alternativ mit 'begin' oder' let', aber mit 'cond' ist das wahrscheinlich einfacher. –

+0

(take l size) (Rolling-Window (cdr l) size) sollte sowohl im sonst Teil keine Notwendigkeit für eine dritte Alternative – X10D

Antwort

3

Wie schreibe ich mehr als einen Ausdruck in if's else in Schläger/Schema?

Nun, das ist nicht wirklich die Frage. Die Frage ist "Wie man ein rollendes Fenster Verfahren mit Schläger bauen?". Wie auch immer, es sieht so aus, als ob Sie wahrscheinlich aus einer anderen Programmiersprache kommen. Die Verarbeitung von verknüpften Listen kann zunächst etwas schwierig sein. Aber denken Sie daran, um die Länge einer Liste zu berechnen, müssen Sie die gesamte Liste durchlaufen. Die Verwendung von length ist hier ein bisschen ein Anti-Muster.

Stattdessen würde ich empfehlen, erstellen Sie eine aux iliary Prozedur in Ihrem rolling-window Verfahren, das das Fenster erstellt, während Sie durch die Liste iterieren. Auf diese Weise müssen Sie Iterationen nicht vergeuden, indem Sie Elemente einer Liste zählen.

Dann, wenn Ihre aux Prozedur jemals zurückkehrt und leeres Fenster, wissen Sie, dass Sie fertig sind, die Fenster für die angegebene Eingabeliste zu berechnen.

(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)) 

Es funktioniert für leere Fenster

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

Und leere Listen zu

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

Eine sehr schöne Lösung. Eine winzige Bemerkung: Da die Schleife 'n' nicht modifiziert, kann sie aus der Argumentliste weggelassen werden. – soegaard

+0

@soegaard danke, dass du das erwischt hast! – naomik

+0

Was ist die Etymologie von xs? – X10D

2

Hier ist eine Alternative:

#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)) 

Ausgang:

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

Die folgende Änderung der OP-Funktion funktioniert. Es enthält eine Outlist, für die der ursprüngliche Standard eine leere Liste ist. Unterlisten werden zu dieser Liste hinzugefügt, bis (length l) weniger als size ist.

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

Testing:

(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) 

Ausgang:

'((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

Alle Verbesserungen auf diesem?

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

Ich habe dir schon gesagt" Länge "ist ein Anti-Muster – naomik

+0

1: Es wäre schön, die Längenprüfung loszuwerden . eine Möglichkeit, die Take-Funktion mit etwas zu komponieren, so dass es stillschweigend endet, wenn die Liste nicht lang genug ist, anstatt eine Liste zu kurz Fehler zu werfen? 2: Ja, es ist weniger effizient, aber ein bisschen lesbarer? – X10D

Verwandte Themen