CS 152 - Lecture 6

Cover page image

Cay S. Horstmann

Scala Documentation

Categories of List Methods

List Operators

Operator Precedence and Associativity

Scala Operators

Lists: Access by Position

Methods with Function Parameters

Tuples

Maps

desert-island

flatMap

  • Given an integer sequence s, it is easy to form all pairs (x, 0):
    val s = (1 to 4).toList
    s.map(x => (x, 0))
        // List((1, 0), (2, 0), (3, 0), (4, 0))
  • What if we want to have all pairs (x, y) where x, y are elements of s?
  • Try it by calling map twice:
    s.map(y => s.map(x => (x, y)))
      // List(List((1,1), (2,1), (3,1), (4,1)),
      //        List((1,2), (2,2), (3,2), (4,2)),
      //        List((1,3), (2,3), (3,3), (4,3)),
      //        List((1,4), (2,4), (3,4), (4,4)))
  • Close, but not quite. To “flatten out” the result, use flatMap instead:
    s.flatMap(y => s.map(x => (x, y)))
      // List((1, 1), (1, 2), (1, 3), (1, 4), (2, 1), (2, 2), ..., (4, 4)) 
  • Folding

    mkString

    Lab

    ???

    Step 1: Warmup

    1. What do take and drop do? Give a brief explanation and an example for each.
    2. What is the difference between take and dropRight?
    3. Look up the definition of span in Scaladoc. Make an example that demonstrates how span works. What is your example, and what value does it produce?
    4. The span method returns a pair. Show how you can get at each of the elements in that pair.

    Step 2: Folding

    1. Use the /: folding operator to concatenate all strings in a List[String], separating them with spaces. For example, if you start with val lst = List("Hello", "Scala", "World"), you should produce an expression involving lst and /: that yields "Hello Scala World". (Hint: It is very easy to get " Hello Scala World". The challenge is to get rid of the first space.
    2. Folding is useful for much more than computing sums and products. Many algorithms that compute a value by making a loop through an array can be obtained with a suitable function whose first argument is the result from the elements that you have seen so far, and whose second argument is the next list element.

      Consider the case of computing the maximum. Find a suitable function whose first argument is the maximum of all elements visited so far, and whose second argument is the next element.

      What the code for your function maximum(lst : List[Int]) : Int? (You may assume that the list has length > 0)

    3. What does this function do?
      def mystery(lst : List[Int]) = 
        (List[Int]() /: lst) ((x, y) => if (y % 2 == 0) x else x :+ y)

      Explain how the function works.

    Step 3. A Puzzle

    Here is a puzzle from a programmer web site:

    Given an array of numbers, return the occurances [sic] of the number 1 in the array. So, if the array contains 1, 2, 11, 13 you would return 4 (as 11 contains two instances of 1). 

    1. Suppose you are given a list of numbers, such as List(1, 2, 11, 13). To get digits of one, it would be better to have strings. How do you get an array of strings? Hint: toString, map
    2. Now look at an individual string such as "1811". How can one count the number of ones? Hint: (1) Strings are collections of characters (2) Try the count method that takes a predicate. For example, (1 to 10).count(_ % 3 == 0) yields 3
    3. Ok, now you need to apply that to each of the strings. How do you do that? (Hint: map)
    4. That gives you a collection of counts. How do you total them up? Hint: reduce, or, if you prefer, look at the scaladoc of Seq for a simpler way.)
    5. Now all together. If lst is a list of integers, how do you get the total number of digits of one?

    Step 4: Misery with Tuples

    1. What is 1 -> 2 -> 3? What is the type of the result?
    2. Write a function flatten that takes such a thing and turns it into an (Int, Int, Int). Use _1, _2
    3. Repeat with destructuring.
    4. What is the result of the following statement, and why?
      val x,y,z = (1,2,3)

    Step 5: If I Had Just One Data Structure...

    1. And if I could just take one method, it would be groupBy. Load all words from a dictionary into a list by calling
      val words = io.Source.fromURL("http://horstmann.com/sjsu/spring2018/cs152/words").getLines.toList
      
      What is words.groupBy(w => w.length)?
    2. Make a map so that myMap('a') yields all words that start with the letter a and so on.
    3. How many words start with a given letter? Hint: myMap.map(...)
    4. Extra credit: Turn this into a list of tuples that is sorted by frequency. Hint: sorted doesn't work because Scala doesn't know how to sort the tuples. There are two other sort methods. One of them wants a function that maps into something that Scala does know how to sort—the easy choice for solving this exercise.
    5. Extra credit: Now do it with the other method (and some tuple misery).