Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><code>collect</code> (defined on <a href="http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/scala/collection/TraversableLike.html" rel="noreferrer">TraversableLike</a> and available in all subclasses) works with a collection and a <code>PartialFunction</code>. It also just so happens that a bunch of case clauses defined inside braces are a partial function (See section 8.5 of the <a href="http://www.scala-lang.org/sites/default/files/linuxsoft_archives/docu/files/ScalaReference.pdf" rel="noreferrer">Scala Language Specification</a> <em>[warning - PDF]</em>)</p> <p>As in exception handling:</p> <pre><code>try { ... do something risky ... } catch { //The contents of this catch block are a partial function case e: IOException =&gt; ... case e: OtherException =&gt; ... } </code></pre> <p>It's a handy way to define a function that will only accept some values of a given type.</p> <p>Consider using it on a list of mixed values:</p> <pre><code>val mixedList = List("a", 1, 2, "b", 19, 42.0) //this is a List[Any] val results = mixedList collect { case s: String =&gt; "String:" + s case i: Int =&gt; "Int:" + i.toString } </code></pre> <p>The argument to to <code>collect</code> method is a <code>PartialFunction[Any,String]</code>. <code>PartialFunction</code> because it's not defined for all possible inputs of type <code>Any</code> (that being the type of the <code>List</code>) and <code>String</code> because that's what all the clauses return.</p> <p>If you tried to use <code>map</code> instead of <code>collect</code>, the the double value at the end of <code>mixedList</code> would cause a <code>MatchError</code>. Using <code>collect</code> just discards this, as well as any other value for which the PartialFunction is not defined.</p> <p>One possible use would be to apply different logic to elements of the list:</p> <pre><code>var strings = List.empty[String] var ints = List.empty[Int] mixedList collect { case s: String =&gt; strings :+= s case i: Int =&gt; ints :+= i } </code></pre> <p>Although this is just an example, using mutable variables like this is considered by many to be a war crime - So please don't do it!</p> <p>A <em>much</em> better solution is to use collect twice:</p> <pre><code>val strings = mixedList collect { case s: String =&gt; s } val ints = mixedList collect { case i: Int =&gt; i } </code></pre> <p>Or if you know for certain that the list only contains two types of values, you can use <code>partition</code>, which splits a collections into values depending on whether or not they match some predicate:</p> <pre><code>//if the list only contains Strings and Ints: val (strings, ints) = mixedList partition { case s: String =&gt; true; case _ =&gt; false } </code></pre> <p>The catch here is that both <code>strings</code> and <code>ints</code> are of type <code>List[Any]</code>, though you can easily coerce them back to something more typesafe (perhaps by using <code>collect</code>...)</p> <p>If you already have a type-safe collection and want to split on some other property of the elements, then things are a bit easier for you:</p> <pre><code>val intList = List(2,7,9,1,6,5,8,2,4,6,2,9,8) val (big,small) = intList partition (_ &gt; 5) //big and small are both now List[Int]s </code></pre> <p>Hope that sums up how the two methods can help you out here!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload