Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group list elements by string-int* pattern

I have a list:

List[Any]("foo", 1, 2, "bar", 3, 4, 5)

I would like to group it's elements this way:

Map("foo" -> List(1,2), "bar" -> List(3,4,5))

I can only imagine a solution in an imperative style with mutable lists and vars, but what is the proper way of solving this task?

like image 462
shutty Avatar asked Jul 14 '26 14:07

shutty


2 Answers

Straightforward.

If the list has elements, take all ints from the tail and drop the rest, which is stored in rest. That is what span does. Then map the head to the ints and recursivly do it for the rest.

def f(a: List[Any]): Map[String, List[Int]] = a match {
  case Nil => Map.empty
  case head :: tail => {
    val (ints, rest) = tail.span(_.isInstanceOf[Int])
    f(rest) + (head.asInstanceOf[String] -> ints.map(_.asInstanceOf[Int]))
  }
}
like image 99
Kigyo Avatar answered Jul 16 '26 09:07

Kigyo


Consider multiSpan as defined in https://stackoverflow.com/a/21803339/3189923 ; then for

val a = List[Any]("foo", 1, 2, "bar", 3, 4, 5)

we have that

val b = a.multiSpan(_.isInstanceOf[String])
b: List[List[Any]] = List(List(foo, 1, 2), List(bar, 3, 4, 5))

and so

b.map { l => (l.head, l.tail) }.toMap
res: Map(foo -> List(1, 2), bar -> List(3, 4, 5))
like image 23
elm Avatar answered Jul 16 '26 07:07

elm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!