At the top of the collection hierarchy is the trait `Traversable`

. Its only abstract operation is `foreach`

:

`def foreach[U](f: Elem => U)`

Collection classes that implement `Traversable`

just need to define this method; all other methods can be inherited from `Traversable`

.

The `foreach`

method is meant to traverse all elements of the collection, and apply the given operation, `f`

, to each element. The type of the operation is `Elem => U`

, where `Elem`

is the type of the collection's elements and `U`

is an arbitrary result type. The invocation of `f`

is done for its side effect only; in fact any function result of `f`

is discarded by `foreach`

.

Traversables are the superclass of `List`

, `Array`

, `Map`

, `Set`

, `Stream`

and more. The methods involved can be applied to each other in a different type.
`++`

appends two `Traversable`

s together. The resulting `Traversable`

is the same type of the first element.

```
val set = Set(1, 9, 10, 22)
val list = List(3, 4, 5, 10)
val result = set ++ list
result.size should be(res0)
val result2 = list ++ set
result2.size should be(res1)
```

`map`

will apply the given function on all elements of a `Traversable`

and return a new collection of the result:

```
val set = Set(1, 3, 4, 6)
val result = set.map(_ * 4)
result.lastOption should be(res0)
```

`flatten`

will "pack" all child `Traversables`

into a single `Traversable`

:

```
val list = List(List(1), List(2, 3, 4), List(5, 6, 7), List(8, 9, 10))
list.flatten should be(res0)
```

`flatMap`

will not only apply the given function on all elements of a `Traversable`

, but all elements within the elements and `flatten`

the results:

```
val list = List(List(1), List(2, 3, 4), List(5, 6, 7), List(8, 9, 10))
val result = list.flatMap(_.map(_ * 4))
result should be(res0)
```

`flatMap`

of `Options`

will filter out all `None`

s but keep the `Some`

s:

```
val list = List(1, 2, 3, 4, 5)
val result = list.flatMap(it => if (it % 2 == 0) Some(it) else None)
result should be(res0)
```

`collect`

will apply a partial function to all elements of a `Traversable`

and return a different collection. In this exercise, a case fragment is a partial function:

```
val list = List(4, 6, 7, 8, 9, 13, 14)
val result = list.collect {
case x: Int if (x % 2 == 0) => x * 3
}
result should be(res0)
```

Two case fragments can be chained to create a more robust result:

```
val list = List(4, 6, 7, 8, 9, 13, 14)
val partialFunction1: PartialFunction[Int, Int] = {
case x: Int if x % 2 == 0 => x * 3
}
val partialFunction2: PartialFunction[Int, Int] = {
case y: Int if y % 2 != 0 => y * 4
}
val result = list.collect(partialFunction1 orElse partialFunction2)
result should be(res0)
```

`foreach`

will apply a function to all elements of a `Traversable`

, but unlike the `map`

function, it will not return anything since the return type is `Unit`

- an equivalent to a `void`

return type in Java/C++:

```
val list = List(4, 6, 7, 8, 9, 13, 14)
list.foreach(num => println(num * 4))
list should be(res0)
```

`toArray`

will convert any `Traversable`

to an `Array`

, which is a special wrapper around a primitive Java array:

```
val set = Set(4, 6, 7, 8, 9, 13, 14)
val result = set.toArray
result.isInstanceOf[Array[Int]] should be(res0)
```

`toList`

will convert any `Traversable`

to a `List`

.

```
val set = Set(4, 6, 7, 8, 9, 13, 14)
val result = set.toList
result.isInstanceOf[List[_]] should be(res0)
```

`toList`

, as well as other conversion methods such as `toSet`

and `toArray`

, will not convert if the collection type is the same:

```
val list = List(5, 6, 7, 8, 9)
val result = list.toList
result eq list should be(res0)
```

`toIterable`

will convert any `Traversable`

to an `Iterable`

. This is a base `trait`

for all Scala collections that define an iterator method to iterate through the collection's elements:

```
val set = Set(4, 6, 7, 8, 9, 13, 14)
val result = set.toIterable
result.isInstanceOf[Iterable[_]] should be(res0)
```

`toSeq`

will convert any `Traversable`

to a `Seq`

which is an ordered `Iterable`

and the superclass to `List`

, `Queue`

, and `Vector`

. `Sequences`

provide a method apply for indexing. Indices range from 0 up to the length of a sequence:

```
val set = Set(4, 6, 7, 8, 9, 13, 14)
val result = set.toSeq
result.isInstanceOf[Seq[_]] should be(res0)
```

`toIndexedSeq`

will convert any `Traversable`

to an `IndexedSeq`

which is an indexed sequence used in `Vectors`

and `Strings`

:

```
val set = Set(4, 6, 7, 8, 9, 13, 14)
val result = set.toIndexedSeq
result.isInstanceOf[IndexedSeq[_]] should be(res0)
```

`toStream`

will convert any `Traversable`

to a `LazyList`

where elements are evaluated as they are needed:

```
val list = List(4, 6, 7, 8, 9, 13, 14)
val result = list.to(LazyList)
result.isInstanceOf[LazyList[_]] should be(res0)
(result take 3) should be(res1)
```

`toSet`

will convert any `Traversable`

to a `Set`

which is a collection of unordered, unique values:

```
val list = List(4, 6, 7, 8, 9, 13, 14)
val result = list.toSet
result.isInstanceOf[Set[_]] should be(res0)
```

`toMap`

will convert any `Traversable`

to a `Map`

. How it's used depends on the original collection; if it's a `List`

or `Seq`

, it should be of parameterized type `Tuple2`

:

```
val list = List("Phoenix" -> "Arizona", "Austin" -> "Texas")
val result = list.toMap
result.isInstanceOf[Map[_, _]] should be(res0)
```

`toMap`

will also convert a `Set`

to a `Map`

; it should be of parameterized type `Tuple2`

:

```
val set = Set("Phoenix" -> "Arizona", "Austin" -> "Texas")
val result = set.toMap
result.isInstanceOf[Map[_, _]] should be(res0)
```

`isEmpty`

is pretty self-evident:

```
val map = Map("Phoenix" -> "Arizona", "Austin" -> "Texas")
map.isEmpty should be(res0)
val set = Set()
set.isEmpty should be(res1)
```

`nonEmpty`

is pretty self-evident too:

```
val map = Map("Phoenix" -> "Arizona", "Austin" -> "Texas")
map.nonEmpty should be(res0)
val set = Set()
set.nonEmpty should be(res1)
```

`size`

provides the size of the traversable:

```
val map = Map("Phoenix" -> "Arizona", "Austin" -> "Texas")
map.size should be(res0)
```

`knownSize`

will return the number of elements if the traversable has a finite end, otherwise `-1`

:

```
val map = Map("Phoenix" -> "Arizona", "Austin" -> "Texas")
map.knownSize should be(res0)
val stream = cons(0, cons(1, LazyList.empty))
stream.knownSize should be(res1)
```

`head`

will return the first element of an ordered collection, or some random element if order is not defined like in a `Set`

or `Map`

:

```
val list = List(10, 19, 45, 1, 22)
list.head should be(res0)
```

`headOption`

will return the first element as an `Option`

of an ordered collection, or some random element if order is not defined. If a first element is not available, then `None`

is returned:

```
val list = List(10, 19, 45, 1, 22)
list.headOption should be(res0)
val list2 = List()
list2.headOption should be(res1)
```

`last`

will return the last element of an ordered collection, or some random element if order is not defined:

```
val list = List(10, 19, 45, 1, 22)
list.last should be(res0)
```

`lastOption`

will return the last element as an `Option`

of an ordered collection, or some random element if order is not defined. If a last element is not available, then `None`

is returned:

```
val list = List(10, 19, 45, 1, 22)
list.lastOption should be(res0)
val list2 = List()
list2.lastOption should be(res1)
```

`find`

will locate the first item that matches the predicate `p`

as `Some`

, or `None`

if an element is not found:

```
val list = List(10, 19, 45, 1, 22)
list.find(_ % 2 != 0) should be(res0)
val list2 = List(4, 8, 16)
list2.find(_ % 2 != 0) should be(res1)
```

`tail`

will return the rest of the collection without the head:

```
val list = List(10, 19, 45, 1, 22)
list.tail should be(res0)
```

`init`

will return the rest of the collection without the last:

```
val list = List(10, 19, 45, 1, 22)
list.init should be(res0)
```

Given a `from`

index, and a `to`

index, `slice`

will return the part of the collection including `from`

, and excluding `to`

:

```
val list = List(10, 19, 45, 1, 22)
list.slice(1, 3) should be(res0)
```

`take`

will return the first number of elements given:

```
val list = List(10, 19, 45, 1, 22)
list.take(3) should be(res0)
```

`take`

is used often with `LazyList`

, since they are also `Traversable`

:

```
def makeLazyList(v: Int): LazyList[Int] = cons(v, makeLazyList(v + 1))
val a = makeLazyList(2)
(a take 3 toList) should be(res0)
```

`drop`

will take the rest of the `Traversable`

except the number of elements given:

```
def makeLazyList(v: Int): LazyList[Int] = cons(v, makeLazyList(v + 1))
val a = makeLazyList(2)
((a drop 6) take 3).toList should be(res0)
```

`takeWhile`

will continually accumulate elements until a predicate is no longer satisfied:

```
val list = List(87, 44, 5, 4, 200, 10, 39, 100)
list.takeWhile(_ < 100) should be(res0)
```

`dropWhile`

will continually drop elements until a predicate is no longer satisfied:

```
val list = List(87, 44, 5, 4, 200, 10, 39, 100)
list.dropWhile(_ < 100) should be(res0)
```

`filter`

will take out all elements that don't satisfy a predicate. (An `Array`

is also `Traversable`

.)

```
val array = Array(87, 44, 5, 4, 200, 10, 39, 100)
array.filter(_ < 100) should be(res0)
```

`filterNot`

will take out all elements that satisfy a predicate:

```
val array = Array(87, 44, 5, 4, 200, 10, 39, 100)
array.filterNot(_ < 100) should be(res0)
```

`splitAt`

will split a `Traversable`

at a position, returning a 2 product `Tuple`

. `splitAt`

is also defined as `(xs take n, xs drop n)`

```
val array = Array(87, 44, 5, 4, 200, 10, 39, 100)
val result = array splitAt 3
result._1 should be(res0)
result._2 should be(res1)
```

`span`

will split a `Traversable`

according to a predicate, returning a 2 product `Tuple`

. `span`

is also defined as `(xs takeWhile p, xs dropWhile p)`

```
val array = Array(87, 44, 5, 4, 200, 10, 39, 100)
val result = array span (_ < 100)
result._1 should be(res0)
result._2 should be(res1)
```

`partition`

will split a `Traversable`

according to a predicate, returning a 2 product `Tuple`

. The left-hand side contains the elements satisfied by the predicate whereas the right hand side contains the rest of the elements. `partition`

is also defined as `(xs filter p, xs filterNot p)`

```
val array = Array(87, 44, 5, 4, 200, 10, 39, 100)
val result = array partition (_ < 100)
result._1 should be(res0)
result._2 should be(res1)
```

`groupBy`

will categorize a `Traversable`

according to a given function and return a map with the results. This exercise uses partial function chaining:

```
val array = Array(87, 44, 5, 4, 200, 10, 39, 100)
val oddAndSmallPartial: PartialFunction[Int, String] = {
case x: Int if x % 2 != 0 && x < 100 => "Odd and less than 100"
}
val evenAndSmallPartial: PartialFunction[Int, String] = {
case x: Int if x != 0 && x % 2 == 0 && x < 100 => "Even and less than 100"
}
val negativePartial: PartialFunction[Int, String] = {
case x: Int if x < 0 => "Negative Number"
}
val largePartial: PartialFunction[Int, String] = {
case x: Int if x > 99 => "Large Number"
}
val zeroPartial: PartialFunction[Int, String] = {
case x: Int if x == 0 => "Zero"
}
val result = array groupBy {
oddAndSmallPartial orElse
evenAndSmallPartial orElse
negativePartial orElse
largePartial orElse
zeroPartial
}
(result("Even and less than 100") size) should be(res0)
(result("Large Number") size) should be(res1)
```

`forall`

will determine if a predicate is valid for all members of a `Traversable`

:

```
val list = List(87, 44, 5, 4, 200, 10, 39, 100)
val result = list forall (_ < 100)
result should be(res0)
```

`exists`

will determine if a predicate is valid for some members of a `Traversable`

:

```
val list = List(87, 44, 5, 4, 200, 10, 39, 100)
val result = list exists (_ < 100)
result should be(res0)
```

`count`

will count the number of elements that satisfy a predicate in a `Traversable`

:

```
val list = List(87, 44, 5, 4, 200, 10, 39, 100)
val result = list count (_ < 100)
result should be(res0)
```

`foldLeft`

will combine an operation starting with a seed and combining from the left. `foldLeft`

takes as a first parameter the initial value of the fold. Once the fold is established, you provide a function that takes two arguments. The first argument is the running total of the operation, and the second element is the next element of the list.

Given a `Traversable (x1, x2, x3, x4)`

, an initial value of `init`

, an operation `op`

, `foldLeft`

is defined as: `(((init op x1) op x2) op x3) op x4)`

```
val list = List(5, 4, 3, 2, 1)
val result = list.foldLeft(0) { (`running total`, `next element`) =>
`running total` - `next element`
}
result should be(res0)
val result2 = list.foldLeft(0)(_ - _) //Short hand
result2 should be(res1)
(((((0 - 5) - 4) - 3) - 2) - 1) should be(res2)
```

`foldRight`

will combine an operation starting with a seed and combining from the right. `foldRight`

takes as a first parameter the initial value of the fold. Once the fold is established, you provide a function that takes two elements. The first is the next element of the list, and the second element is the running total of the operation.

Given a `Traversable (x1, x2, x3, x4)`

, an initial value of `init`

, an operation `op`

, `foldRight`

is defined as: `x1 op (x2 op (x3 op (x4 op init)))`

```
val list = List(5, 4, 3, 2, 1)
val result = list.foldRight(0) { (`next element`, `running total`) =>
`next element` - `running total`
}
result should be(res0)
val result2 = list.foldRight(0)(_ - _) //Short hand
result2 should be(res1)
(5 - (4 - (3 - (2 - (1 - 0))))) should be(res2)
```

`reduceLeft`

is similar to `foldLeft`

, except that the seed is the head value:

```
val intList = List(5, 4, 3, 2, 1)
intList.reduceLeft {
_ + _
} should be(res0)
val stringList = List("Do", "Re", "Me", "Fa", "So", "La", "Te", "Do")
stringList.reduceLeft {
_ + _
} should be(res1)
```

`reduceRight`

is similar to `foldRight`

, except that the seed is the last value:

```
val intList = List(5, 4, 3, 2, 1)
intList.reduceRight {
_ + _
} should be(res0)
val stringList = List("Do", "Re", "Me", "Fa", "So", "La", "Te", "Do")
stringList.reduceRight {
_ + _
} should be(res1)
```

There are some methods that take much of the folding work out by providing basic functionality. `sum`

will add all the elements, `product`

will multiply, `min`

would determine the smallest element, and `max`

the largest:

```
val intList = List(5, 4, 3, 2, 1)
intList.sum should be(res0)
intList.product should be(res1)
intList.max should be(res2)
intList.min should be(res3)
```

The naive recursive implementation of `reduceRight`

is not tail recursive and would lead to a stack overflow if used on larger traversables.
However, `reduceLeft`

can be implemented with tail recursion.

To avoid the potential stack overflow with the naive implementation of `reduceRight`

we can easily implement it based on `reduceLeft`

by reverting the list and the inverting the reduce function.
The same applies for folding operations.

There is also a `reduce`

(and `fold`

) available, which works exactly like `reduceLeft`

(and `foldLeft`

) and it should be the prefered method to call unless there is a strong reason to use `reduceRight`

(or `foldRight`

).

```
val intList = List(5, 4, 3, 2, 1)
intList.reduceRight((x, y) => x - y) should be(res0)
intList.reverse.reduceLeft((x, y) => y - x) should be(res1)
intList.reverse.reduce((x, y) => y - x) should be(res2)
```

`transpose`

will take a traversable of traversables and group them by their position in it's own traversable, e.g.:
`((x1, x2),(y1, y2)).transpose = (x1, y1), (x2, y2)`

or
`((x1, x2, x3),(y1, y2, y3),(z1, z2, z3)).transpose = ((x1, y1, z1), (x2, y2, z2), (x3, y3, z3))`

```
val list = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
list.transpose should be(List(res0, res1, res2))
val list2 = List(List(1), List(4))
list2.transpose should be(List(res3))
```

`mkString`

will format a `Traversable`

using a given string as the delimiter:

```
val list = List(1, 2, 3, 4, 5)
list.mkString(",") should be(res0)
```

`mkString`

will also take a beginning and ending string to surround the list.:

```
val list = List(1, 2, 3, 4, 5)
list.mkString(">", ",", "<") should be(res0)
```

`addString`

will take a StringBuilder to add the contents of list into the builder.

```
val stringBuilder = new StringBuilder()
val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
stringBuilder.append("I want all numbers 6-12: ")
list.filter(it => it > 5 && it < 13).addString(stringBuilder, ",")
stringBuilder.mkString should be(res0)
```