joesan
joesan

Reputation: 15345

Scala Sequence to a Sequence of Sequence

I have a Sequence as:

Seq(1,2,3) 

I'm trying to get a Sequence of a Sequence that would look like this:

Seq(Seq(1), Seq(1,2), Seq(1,2,3))

Here is what I came up with:

  def pop(acc: Seq[Seq[Int]], elems: Seq[Int]): Seq[Int] = elems match {
    case Nil => acc.flatten
    case x :: xs =>
      pop(acc ++ Seq(Seq(x, xs.head)), xs.tail)
  }

As expected, I'm hitting a NoSuchElementException on the place where I do xs.head. I'm sure there must be something that I"m doing wrong! May be I'm missing. This one does not give me the expected result, but this was just a try!

Edit: The original goal was to split a String that comes in as:

"1.2.3" to a Sequence of Strings as Seq("1), Seq("1.2"), Seq("1.2.3")

To achieve this, I'm first splitting based on the . character, going over the resulting Sequence and concatenating them again with the . character.

Upvotes: 3

Views: 2638

Answers (5)

Tzach Zohar
Tzach Zohar

Reputation: 37822

You can also achieve this (not too efficiently, but concisely) using inits:

scala> Seq(1,2,3).inits.toList.reverse.tail
res0: List[Seq[Int]] = List(List(1), List(1, 2), List(1, 2, 3))

EDIT: Per question update, a similar way to find all prefixes of a String up to a "." delimiter would be to just treat the String as a sequence of Chars:

"1.2.3".inits.filter(s => s.nonEmpty && !s.endsWith(".")).toList.reverse

Upvotes: 5

Landei
Landei

Reputation: 54574

 Seq(1,2,3).scanLeft(Seq[Int]())(_ :+ _).tail

If the list is longer, appending to the end of a Seq in scanLeft might become too expensive. In that case you could prepend to a List, and add a reverse step, or use some mutable builder (like ListBuffer).

Upvotes: 7

Paweł Jurczenko
Paweł Jurczenko

Reputation: 4471

val input = Seq(1,2,3)
val result = (1 to input.length).map(input.take).toList // List(List(1), List(1, 2), List(1, 2, 3))

Upvotes: 4

meucaa
meucaa

Reputation: 1515

If your Seq does not have duplicates and is ordered, you can do:

val yourSeq = Seq(1,2,3)
yourSeq.map(e => Seq(yourSeq.takeWhile(_ <= e))).flatten

Upvotes: 0

joesan
joesan

Reputation: 15345

Almost there:

  def pop(acc: Seq[Seq[Int]], elems: Seq[Int]): Seq[Seq[Int]] = elems match {
    case Nil => acc
    case x :: xs =>
      if (acc.isEmpty)
        pop(Seq(Seq(x)), xs)
      else
        pop(acc ++ Seq(acc.last ++ Seq(x)), xs)
  }

Upvotes: 0

Related Questions