Lecture 9 Slides - Manipulating Composite Data

1 of 54

Lecture 9

Manipulating Composite Data - Processing the Real World

2 of 54

Example: an album database

We can represent our music collection as a list of album objects from lecture 8

> (define database

(list (make-album "The white album"

"The Beatles"

"Rock")

(make-album "Sgt. Pepper’s Lonely Hearts Club Band"

"The Beatles"

"Rock")

(make-album "Pod"

"The Breeders"

"Rock")

(make-album "Dummy"

"Portishead"

"Triphop")))

> database

(list (make-album "The white album" "The Beatles" "Rock")

(make-album "Sgt. Pepper’s Lonely Hearts Club Band"

"The Beatles" "Rock")

(make-album "Pod" "The Breeders" "Rock")

(make-album "Dummy" "Portishead" "Triphop"))

3 of 54

list iteration:�searching lists

4 of 54

Searching (filtering)

(filter predicate list)�;; filter: (T -> Boolean) (listof T) -> (listof T)�

Returns all the list items satisfying predicate.

Examples

> (filter odd? (list 1 2 3 4 5 6))

(list 1 3 5)

> (filter number? (list 1 2 "three"))

(list 1 2)

> (filter string? (list 1 2 "three"))

(list "three")

5 of 54

filter in Action

5

0

1

2

3

4

6

Input List

6 of 54

filter in Action

5

0

1

2

3

4

6

even?

Output List

7 of 54

filter in Action

5

0

1

2

3

4

6

even?

0

Output List

8 of 54

filter in Action

5

0

1

2

3

4

6

even?

0

Output List

9 of 54

filter in Action

5

0

1

2

3

4

6

even?

0

Output List

10 of 54

filter in Action

5

0

1

2

3

4

6

even?

0

Output List

2

11 of 54

filter in Action

5

0

1

2

3

4

6

0

Output List

2

4

6

12 of 54

Finding all the Beatles albums

How do we find out what all the Beatles albums are in our database?

> ???

13 of 54

Finding all the Beatles albums

How do we find out what all the Beatles albums are in our database?

What if we filter using our Beatles? predicate from last time?

> ???

14 of 54

Finding all the Beatles albums

How do we find out what all the Beatles albums are in our database?

What if we filter using our Beatles? predicate from last time?

;; Beatles?: album -> Boolean

;; Determines whether an album is by the

;; Beatles

> (define Beatles? (lambda (album)

(string=? (album-artist album)

"The Beatles"))

> (filter Beatles? database)

(list (make-album "The white album"

"The Beatles"

"Rock")

(make-album "Sgt. Pepper’s Lonely Hearts Club Band"

"The Beatles"

"Rock"))

15 of 54

Is this any different?

> (filter (λ (album)

(string=? (album-artist album)

"The Beatles"))

database)

(list (make-album "The white album"

"The Beatles"

"Rock")

(make-album "Sgt. Pepper’s Lonely Hearts Club Band"

"The Beatles"

"Rock"))

16 of 54

Is this any different?

> (filter (λ (album)

(string=? (album-artist album)

"The Beatles"))

database)

(list (make-album "The white album"

"The Beatles"

"Rock")

(make-album "Sgt. Pepper’s Lonely Hearts Club Band"

"The Beatles"

"Rock"))

  • Of course not: remember that Beatles? is just a variable.
    • Its value happens to be (λ (album) (string=? …))
  • So we can perfectly well just type its value rather than the name
  • But if we’re going to have to type it repeatedly then it makes more sense to name it and just type the name

17 of 54

Now we can get a list of Beatles albums

What other questions can we ask?

18 of 54

Now we can get a list of Beatles albums

What other questions can we ask?

How about, how many Beatles albums do we have in the database?

19 of 54

Now we can get a list of Beatles albums

What other questions can we ask?

How about, how many Beatles albums do we have in the database?

Step 1. Get all the Beatles Albums

Step 2. Count how many there are.

20 of 54

How do you count the Beatles albums?

> (length (filter Beatles? database))

2

Reminder: you don’t have to memorize all these functions!

  • For quizzes, we’ll provide you with the names and arguments for all the list (and other) functions you’ll need
  • The only thing you need to know like the back of your hand is our special forms and rules of execution.

21 of 54

list iteration:�transforming lists

22 of 54

Mapping

(map function list)�;; map: (In -> Out) (listof In) -> (listof Out)

Runs function on every element and Outputs their return values as a new list

i.e. (map func (list a b c)) is equivalent to (list (func a) (func b) (func c))

Examples> (map (lambda (num) (* -1 num)) (list 1 2 3 4))

(list -1 -2 -3 -4)

23 of 54

map in Action

0

1

2

3

even?

Output List

24 of 54

map in Action

Output List

true

0

1

2

3

even?

25 of 54

map in Action

Output List

true

0

1

2

3

even?

false

26 of 54

map in Action

Output List

true

0

1

2

3

false

true

even?

27 of 54

map in Action

Output List

true

0

1

2

3

false

true

false

28 of 54

Getting the genres of all albums

> (map album-genre database)

(list "Rock" "Rock" "Rock"

"Triphop")

> (remove-duplicates

(map album-genre database))

(list "Rock" "Triphop")

Note: remove-duplicates takes a list and returns a new

copy of it with any duplicate elements removed.

Note 2: It’s not included in the student languages for Racket so instead we'll provide it for you in a separate RKT file (like iterated-images) for Tutorial 2 and Exercise 3

(define database

(list (make-album "The white album"

"The Beatles"

"Rock")

(make-album

"Sgt. Pepper’s Lonely Hearts"

"The Beatles"

"Rock")

(make-album "Pod"

"The Breeders"

"Rock")

(make-album "Dummy"

"Portishead"

"Triphop")))

29 of 54

list iteration:�aggregating lists

Using foldl and foldr

30 of 54

Folding

(foldl func start-value list)

(foldr func start-value list)

;; foldl/foldr : (X Y -> Y) Y (listof X) -> Y

Aggregates (or folds together) all the values of list together using func

(foldl func start (list a b c)) is equivalent to:� (func c (func b (func a start)))

(foldr func start (list a b c) is equivalent to

(func a (func b (func c start))

  • Mostly used for summing or multiplying elements of a list
  • Examples
    • (foldl + 0 (list 1 2 3)) returns: (+ 3 (+ 2 (+ 1 0))) = 6
    • (foldl max 0 (list 1 2 3)) returns: (max 3 (max 2 (max 1 0))) = 3

31 of 54

foldl and foldr in Action

Output Value

0

1

2

3

+

(foldl + 0 (list 1 2 3))

32 of 54

foldl and foldr in Action

Output Value

1

2

3

+

(foldl + 0 (list 1 2 3))

(+ 1 0)

33 of 54

foldl and foldr in Action

Output Value

1

2

3

+

(foldl + 0 (list 1 2 3))

(+ 1 0)

34 of 54

foldl and foldr in Action

Output Value

1

2

3

+

(foldl + 0 (list 1 2 3))

(+ 2 (+ 1 0))

35 of 54

foldl and foldr in Action

Output Value

1

2

3

+

(foldl + 0 (list 1 2 3))

(+ 3 (+ 2 (+ 1 0)))

36 of 54

foldl and foldr in Action

Output Value

1

2

3

(foldl + 0 (list 1 2 3))

6

37 of 54

foldl and foldr in Action

Output Value

0

1

2

3

+

(foldr + 0 (list 1 2 3))

38 of 54

foldl and foldr in Action

Output Value

(+ 3 0)

1

2

3

+

(foldr + 0 (list 1 2 3))

39 of 54

foldl and foldr in Action

Output Value

(+ 2 (+ 3 0))

1

2

3

+

(foldr + 0 (list 1 2 3))

40 of 54

foldl and foldr in Action

Output Value

(+ 1 (+ 2 (+ 3 0)))

1

2

3

+

(foldr + 0 (list 1 2 3))

41 of 54

foldl and foldr in Action

Output Value

6

1

2

3

(foldr + 0 (list 1 2 3))

42 of 54

Averaging using foldl

  • We can find the sum of the elements in a list by adding them using foldl

  • And we can compute the average by dividing it by the length

;; sum: (listof number) -> number

;; The of the numbers in the list

(define sum

(λ (list) (foldl + 0 list)))

(check-expect (sum (list 1 2 3))

6)

;; mean: (listof number) -> number

;; The average of the numbers in the list

(define mean

(λ (list)

(∕ (sum list)

(length list))))

(check-expect (mean (list 1 2 3))

2)

43 of 54

misc list functions

44 of 54

Testing items in a list

(ormap predicate list)�;; ormap: (T -> Boolean)�;; (listof T)�;; -> boolean

True when any item satisfies predicate

(andmap predicate list)�;; andmap: (T -> Boolean)�;; (listof T)�;; -> boolean

�True when every item in satisfies predicate

(define database

(list (make-album

"The white album"

"The Beatles"

"Rock")

(make-album

"Sgt. Pepper’s Lonely Hearts"

"The Beatles"

"Rock”)

(make-album "Pod"

“The Breeders”

“Rock”)

(make-album “Dummy”

“Portishead”

“Triphop”)))

(ormap Beatles? database)

#true

(andmap Beatles? database)

#false

45 of 54

Building arbitrary lists

(build-list n function)

Creates a list of n numbers by applying function to the integers from 0 to n - 1 in order.

> (build-list 5 (lambda (x) (* x x)))

(list 0 1 4 9 16)

46 of 54

Last, but not least, the apply function

(apply function list)

Calls function and passes it the elements of list as inputs

> (apply + (list 1 2 3 4 5))

15

> (apply max (list 1 2 3 4 5 1))

5

> (apply list-ref

(list (list 1 2 3 4 5)

2))

3

> (apply append

(list (list 1 2)

(list 3 4)

(list 5 6)))

(list 1 2 3 4 5 6)

47 of 54

The mystery revealed

(define iterated-overlay

(λ (func count)(apply overlay (build-list count func))))

  • First, build-list calls func with inputs from 0 to count-1
    • And returns their results as a single list
  • Then, apply calls overlay with the elements of that list as arguments
  • Finally, overlay makes them into a single picture

48 of 54

A cookbook

49 of 54

How do I search for something?

How do I find all the elements of a list that have some property?

    • Example: all the odd numbers in a list
  • Step 1: Write a function to recognize the elements you’re looking for
    • If you already have a function written, just use that
    • Otherwise, write a λ
      • It should take an element as input
      • Return a Boolean as a result
  • Step 2: Pass that function and the list to filter

50 of 54

How do I search for something?

  • How do I find all the elements of a list that have some property?
    • (filter predicate? list), or
    • (filter (λ (element-name) test)� list)
  • Examples:
    • (filter integer? (list 1 2 3.5 4))returns: (list 1 2 4)
    • (filter (λ (number)� (> number 3))� (list 1 2 3.5 4))�returns: (list 3.5 4)

51 of 54

How do I get info about elements of a list?

How do I find some attribute of every element of a list?

    • Or more generally, compute something about every element
    • Examples: get the title of every album, add one to every element
  • Step 1: Write a function to compute the attribute for one element
    • If you already have a function written, just use that
    • Otherwise, write a λ
      • It should take an element as input
      • Return the desired output for that element
  • Step 2: Pass that function and the list to map

52 of 54

How do I get info about elements of a list?

  • How do I find some attribute of every element of a list?
    • (map property-function list), or
    • (map (λ (element-name) compute-property)� list)
  • Examples:
    • (map abs (list 1 -2 3 -4)) returns: (list 1 2 3 4)
    • (map (λ (number)� (+ number 1))� (list 1 2 3.5 4))�returns: (list 2 3 4.5 5)

53 of 54

How do I summarize a list?

How do I aggregate all the items in a list into one item (e.g. the sum, product or max of the list)?

    • i.e. how do I “squish” all the elements down into one value
    • Example: sum all the numbers in a list into one number
  • Step 1: Write a function to aggregate two values
    • If you already have a function written, just use that
    • Otherwise, write a λ
      • It should take an two values as input
      • Return the aggregate value
  • Step 2: decide what the answer should be for the empty list
  • Step 3: Pass that function, the empty list answer, and the list to foldl or foldr

54 of 54

How do I summarize a list?

  • How do I aggregate all the items in a list into one item (e.g. the sum, product or max of the list)?
    • (foldl aggregator empty-list-value list), or
    • (foldl (λ (element aggregate-so-far) new-aggregate)� empty-list-valuelist)
  • Examples:
    • (foldl + 0 (list 1 -2 3 -4)) returns: -2
    • (foldl max 0 (list 1 2 3.5 4)) returns: 4