2016-04-24 16 views
1

Ich versuche, die folgende Funktion zu schreiben, die 2 Listen von Listen erhält und das kartesische Produkt dieser Listen zurückgibt.Schema - Verwenden von Foldr innerhalb Karte und machen die Foldr Proc verwenden das aktuelle Element aus der Map Iteration

hier ist, was ich schrieb:

;; Signature: mix-rows(rows1 rows2) 
;; Purpose: returns a list of rows of the cartesian product of both rows 
;; Type: [ List(Row) * List(Row) -> List(Row) ] 
;; Tests: 
;; (mix-rows (list '(10 11) '(20 21)) (list '('u 'v) '('p 'q))) 
;; ==> ((10 11 'u 'v) 
;;  (10 11 'p 'q) 
;;  (20 21 'u 'v) 
;;  (20 21 'p 'q)) 
(define mix-rows 
    (lambda (rows1 rows2) 
    (map (lambda (row1) 
      (foldr (lambda (row2) 
        (append row1 row2)) 
        '() 
       rows2)) 
     rows1))) 

aus irgendeinem Grunde das letzte Lambda nicht row1 erkennen, die von der Funktionskarte gegeben wurden durch Rows1 iterieren.

Ich möchte das letzte Lambda durch rows2 iterieren und jedes Element an row1 anhängen und nachdem alle rows2 Elemente angefügt wurden row1 wird zum nächsten Element in rows1 wechseln.

warum möchte das Lambda row1 erkennen?

danke.

+0

Sie wahrscheinlich nicht zum doppelten Zitat "uvpq", verwenden Sie einfach ''(uv)' und '' (pq)', die gezuckerte Versionen von '(Liste (Zitat u) (Zitat v)) und '(Liste (Zitat p) (Zitat q))' – naomik

Antwort

1

Zuerst, wenn alles, was Sie wollen, eine cartesian-product Funktion ist, können Sie cartesian-product von racket/list verwenden.

> (cartesian-product 
    (list '(10 11) '(20 21)) 
    (list '('u 'v) '('p 'q))) 
'(((10 11) ('u 'v)) ((10 11) ('p 'q)) ((20 21) ('u 'v)) ((20 21) ('p 'q))) 

Ihr Testfall ist etwas anders als das, weil Ihr Testfall der inneren Listen Spleißstellen und dies nicht tut. Aber wenn Sie das brauchen, können Sie es einfach mit (map append* ...) beheben. Die Funktion append* flacht eine Liste von Listen um eine Ebene nach unten ab.

> (define (mix-rows rows1 rows2) 
    (map append* (cartesian-product rows1 rows2))) 
> (mix-rows 
    (list '(10 11) '(20 21)) 
    (list '('u 'v) '('p 'q))) 
'((10 11 'u 'v) (10 11 'p 'q) (20 21 'u 'v) (20 21 'p 'q)) 

Obwohl, wenn Sie es von Grund auf neu entwerfen wollen, das Problem bei der Implementierung ist, dass foldr erwartet eine Funktion (X Y -> Y), eine Zwei-Argument Funktion, aber sie gab es eine Funktion (Row -> Row), eine ein Argument Funktion. Du könntest das beheben, aber von dem, was ich sehen kann, brauchst du überhaupt keinen foldr. Wahrscheinlich hast du dort auch eine map gemeint.

(define mix-rows 
    (lambda (rows1 rows2) 
    (map (lambda (row1) 
      (map (lambda (row2) 
        (append row1 row2)) 
       rows2)) 
     rows1))) 

Obwohl dies Ihr Testfall noch ausfällt, produziert

> (mix-rows 
    (list '(10 11) '(20 21)) 
    (list '('u 'v) '('p 'q))) 
'(((10 11 'u 'v) (10 11 'p 'q)) ((20 21 'u 'v) (20 21 'p 'q))) 

Um dieses zusätzliche Schicht von verschachtelten Listen loszuwerden, können Sie append* verwenden Sie diese Liste von Listen eine Ebene nach unten zu glätten.

;; Signature: mix-rows(rows1 rows2) 
;; Purpose: returns a list of rows of the cartesian product of both rows 
;; Type: [ List(Row) * List(Row) -> List(Row) ] 
;; Tests: 
;; (mix-rows (list '(10 11) '(20 21)) (list '('u 'v) '('p 'q))) 
;; ==> ((10 11 'u 'v) 
;;  (10 11 'p 'q) 
;;  (20 21 'u 'v) 
;;  (20 21 'p 'q)) 
(define mix-rows 
    (lambda (rows1 rows2) 
    (append* 
    (map (lambda (row1) 
      (map (lambda (row2) 
        (append row1 row2)) 
       rows2)) 
      rows1)))) 

Wenn Sie jedoch ein echtes cartesianischen Produkt wünschen, ohne die Zeilen Spleißen, können Sie sie beheben, indem (append row1 row2) zu (list row1 row2) ändern.

(define mix-rows 
    (lambda (rows1 rows2) 
    (append* 
    (map (lambda (row1) 
      (map (lambda (row2) 
        (list row1 row2)) 
       rows2)) 
      rows1)))) 

Dann entspricht es was cartesian-product tut.