2012-04-12 1 views
3

Ich muss von einer Liste nur die Werte, die ungerade sind, so dass ich versuche, meine Liste mit Auto-und CDR-Funktionen zu brechen. Ich habe einen rekursiven Funktionsaufruf, der prüft, ob das Auto eine Liste zurückgibt, dann brich es weiter mit Auto und CDR, ansonsten übergebe einfach das erste Element an einen Funktionsaufruf, ob Odd.Wie zu brechen (11 (12 13)) mit Auto und Cdr in Scheme

Das Problem mit dem Spezialfall (10 11 (12 13)) ist, dass Wagen 10 CDRs kehren zurück (11 (12 13))

dann in zweiter Iteration Auto zurückkehrt (11 (12 13)) cdr returns (11 (12 13))

so wie kann ich meine Liste mit Auto und CDR weiter brechen. Ich muss die Klammern in meiner letzten Antwort beibehalten und nur die Liste mit ungeraden Werten von ganzen Zahlen zurückgeben.

+1

Ich bin verwirrt, das 'Auto' von' (11 (12 13)) 'ist' 11'. Es sieht so aus, als hätten Sie einen logischen Fehler in Ihrem Programm, denn auf hohem Niveau klingt der Ansatz, den Sie beschreiben, so, wie er funktionieren würde, solange Sie vorsichtig sind, wenn Sie auf eine Liste wie zB mit '((13)) '. –

Antwort

4

Für eine Funktion, die auf einer beliebigen verschachtelten Liste arbeiten muss, finde ich es einfach, zuerst die flache Liste Version (Filter-Odd in unserem Fall) zu schreiben und sie dann zu bearbeiten, um die verschachtelte Version zu erzeugen -odd *)

Zuerst für normale Filter ungerade

(define filter-odd 
    (lambda (ls) 
     (cond 
     [(null? ls) '()] 
     [(odd? (car ls)) (cons (car ls) (filter-odd (cdr ls)))] 
     [else (filter-odd (cdr ls))]))) 

jetzt für Filter-ungerade * (eine rechte Seite wird als eine Übung gelassen werden (obwohl es scheint, wie Sie die Antwort wissen von Ihrem Frage))

(define filter-odd* 
    (lambda (ls) 
     (cond 
     [(null? ls) '()] 
     [(list? (car ls)) #| Do something with both car and cdr of ls |# ] 
     [(odd? (car ls)) (cons (car ls) (filter-odd* (cdr ls)))] 
     [else (filter-odd* (cdr ls))]))) 

Als eine Anmerkung kann dieses Entwurfsmuster verwendet werden, um zu helfen, jedes rekursive Programm zu schreiben und es von nur Arbeiten auf flachen Listen zu Arbeiten auf beliebig tiefen Listen zu konvertieren.

1

Hier ist eine allgemeine Lösung, für Listen mit einer beliebigen Ebene der Verschachtelung:

(define (odds-list lst) 
    (cond ((null? lst) '())     ; the list is empty 
     ((not (list? (car lst)))   ; first element is not a list 
     (if (odd? (car lst))    ; element is odd 
      (cons (car lst) (odds-list (cdr lst))) ; build the returned list 
      (odds-list (cdr lst))))  ; element is even 
     (else (cons (odds-list (car lst)) ; first element is a list 
        (odds-list (cdr lst)))))) 

Beachten Sie, dass drei Fälle in Betracht gezogen werden müssen:

  1. Wenn die Liste leer ist
  2. Wenn die erstes Element der Liste ist keine Liste
  3. Wenn das erste Element der Liste eine Liste ist

Für den zweiten Fall müssen zwei weitere Fälle in Betracht gezogen werden:

  1. Wenn das Element ungerade ist, dann kehrten wir es in die Liste aufnehmen
  2. Wenn das Element selbst ist, wir es überspringen und mit dem nächsten Element
+0

Vielen Dank! Es löst mein Problem.Froh für die Hilfe :)! – Basmah

0

Hier ist mein nehmen:

(define filter* 
    (lambda (e f) 
    (cond ((pair? e) 
      (append (filter* (car e) f) 
        (filter* (cdr e) f))) 
      ((null? e) '()) 
      ((f e) (list e)) 
      (else '())))) 

und dann können Sie tun:

> (filter* '(1 (2 . 3) ((4 . 5))) even?) 
(2 4) 
> (filter* '(1 (2 . 3) ((4 . 5))) odd?) 
(1 3 5)