Wednesday, 21 November 2012

Exercise 185: Create the function make-ranking, which consumes a list of ranked song titles and produces an HTML table representation.


Exercise 185: Create the function make-ranking, which consumes a list of ranked song titles and produces an HTML table representation. 

Consider this example:
(define one-list
  '("Asia: Heat of the Moment"
    "U2: One"
    "The White Stripes: Seven Nation Army"))

The type of output expected here isn't really clarified. You could argue we should provide an html string (eg "<html><body>...</body></html>") or the HTML table representation we were given as an example in the previous question. I'm opting for the latter as it matches better the previous question in the book.


(define (ranking los)
  (reverse (add-ranks (reverse los))))

(define (add-ranks los)
  (cond
    [(empty? los) '()]
    [else (cons (list (length los) (first los))
                (add-ranks (rest los)))]))

(define one-list
  '("Asia: Heat of the Moment"
    "U2: One"
    "The White Stripes: Seven Nation Army"))


; draws a single cell of data wrapped in a td
; Song -> Nested List
(define (make-cell data)
  `(td ,data))

; makes a row for the song table based on a list of values (eg ranking + title)
(define (make-row l)
  (cond ((empty? l) '())
        (else (cons (make-cell (first l))
                    (make-row (rest l))))))

; simple test on a single row. These tests are the same, I am just practising the new list notation.
(check-expect (make-row '(1 "A"))
              (list (list 'td 1) (list 'td "A") ))
(check-expect (make-row '(1 "A"))
              '((td 1) (td "A")))


; creates a list row for each song in the list
(define (make-rows los)
  (cond ((empty? los) empty)
        (else  `( (tr ,@(make-row (first los)))
                  ,@(make-rows (rest los))))))

; a short happy test. should split our short list into two rows
; I really struggled to get this function working before I wrote this test.
; Once I had the test, the function was simple.
(check-expect(make-rows (ranking short-list))
              '((tr (td 1) (td "A")) (tr (td 2) (td "B"))))

; creates a list based table structure
(define (make-table-list los)
  `(table ((border 1))
           ,@los))

; happy test - this should produce a complete table list
(check-expect (make-table-list (make-rows (ranking short-list)))
              '(table ((border 1))
                      (tr (td 1) (td "A"))
                      (tr (td 2) (td "B"))))
                     
; helper function that wraps the ranking and name into a table list from a list
(define (make-table-helper list)
  (make-table-list (make-rows (ranking list))))


When run, we get:


(make-table-helper one-list)

(list 'table (list (list 'border 1)) (list 'tr (list 'td 1) (list 'td "Asia: Heat of the Moment")) (list 'tr (list 'td 2) (list 'td "U2: One")) (list 'tr (list 'td 3) (list 'td "The White Stripes: Seven Nation Army")))

No comments:

Post a Comment