Reimeus
Reimeus

Reputation: 159844

Splitting out 3 or more Arrays in Scala

Martin Odersky gives this example to split out an array into 2 collections:

val people: Array[Person]
val (minors, adults) = people partition (_.age < 18)

class Person(val name: String, val age: Int)

What is the best way to split out into 3 or more arrays:

val (minors, adults, seniors) = people partition?? x < 18, 18 < x < 65, x > 65 // ?

Upvotes: 2

Views: 668

Answers (4)

Luigi Plinge
Luigi Plinge

Reputation: 51109

def multiPartition[T: Manifest](xs: Traversable[T])(fs: T => Boolean *) = {
  val builders = Vector.fill(fs.length)(ArrayBuffer.empty[T])
  for (e <- xs) {
    val i = fs.indexWhere(f => f(e))
    if (i >= 0) builders(i) += e
  }
  builders.map(_.toArray)    
}

Example usage would be:

val Seq(minors, adults, seniors) = 
    multiPartition(people)(_.age < 18, _.age < 65, _ => true)

so each term in the second arg list is a "bucket", with _ => true being "everything else".

This returns Arrays. I made a very similar version that spits out your original collection type here, although I don't know how to get that to work for Arrays as well.

Upvotes: 3

Eastsun
Eastsun

Reputation: 18869

You may use the method groupBy:

case class Person(name: String, age: Int)

val people = Array(Person("A",1),Person("B",2),Person("C",14),Person("D",19),Person("E",70))

def typeByAge(p: Person): String = 
  if(p.age < 4) "BABY"
  else if(p.age < 18) "MINOR"
  else if(p.age < 65) "ADULT"
  else "OLD"

val g = people groupBy typeByAge

val (babys,minors,adults,olds) = (g("BABY"),g("MINOR"),g("ADULT"),g("OLD"))

Upvotes: 2

Brian
Brian

Reputation: 20285

This will return a Tuple3 like you note in the question of minors, adults, and seniors. There is probably a more efficient and general approach though.

Tuple3(people.filter(_.age < 18), people.filter(p => p.age > 18 && p.age < 65), people.filter(_.age > 65))

Upvotes: 2

Kaito
Kaito

Reputation: 1765

Doing that with a one-liner would be probably less pretty.

val (minors, older) = people partition {_.age < 18}
val (adults, seniors) = older partition {_.age < 65}    

Upvotes: 7

Related Questions