title: How to groupBy while discarding some elements of a collection
body: <p>I'd like to group a sequence into a map of sequences, based on a discriminator of type <code>Option</code>, similar to the result of the <code>groupBy</code> method but where values resulting in <code>None</code> are discarded. Or perhaps, grouping by a <code>PartialFunction</code> discriminator and discarding those for which the partial function is not defined.</p>
  
  <p>Here is a concrete example:</p>
  
  <p>I have a collection of names, and a collection of namespaces. Some, but not all, of the names belong in a valid namespace, and I want to group those that do into a Map, discarding those that don't.</p>
  
  <p>Currently my solution is equivalent to:</p>
  
  <pre><code>val names = List("ns1.foo", "ns2.bar", "ns2.baz", "froznit")
  val namespaces = List("ns1", "ns2")
  
  def findNamespace(n: String): Option[String] = namespaces.find(n.startsWith)
  
  val groupedNames = names.groupBy(findNamespace).collect {
    case (Some(ns), name) =&gt; (ns, name)
  }
  // Map((ns1,List(ns1.foo)), (ns2,List(ns2.bar, ns2.baz)))
  </code></pre>
  
  <p>My concern about this solution is that, using <code>names.groupBy(findNamespace)</code>, I'm creating an intermediate Map which contains all the names I don't care about, under the key <code>None</code>. If the number of names which I discard becomes large, this solution becomes less attractive.</p>
  
  <p>My attempt to avoid this is a bit of a trainwreck, though:</p>
  
  <pre><code>val groupedNames =
    names.
      map(n =&gt; (findNamespace(n), n)).
      collect({ case (Some(ns), n) =&gt; (ns, n) }).
      groupBy(_._1).
      map({ case (ns, names) =&gt; (ns, names.map(_._2)) })
  </code></pre>
  
  <p>If you were to solve this in a smarter way, what would it be?</p>
  
  <hr>
  
  <p>Edit: ideally, the solution should only call <code>findNamespace(name)</code> once for each name, and build the Map using only the <code>Option[String]</code> values, without calling a separate <code>hasNamespace(name)</code> predicate.</p>