Scala Split Seq or List by Delimiter - scala
Let's say I have a sequence of ints like this:
val mySeq = Seq(0, 1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
I want to split this by let's say 0 as a delimiter to look like this:
val mySplitSeq = Seq(Seq(0, 1, 2, 1), Seq(0, -1), Seq(0, 1, 2, 3, 2))
What is the most elegant way to do this in Scala?
This works alright
mySeq.foldLeft(Vector.empty[Vector[Int]]) {
case (acc, i) if acc.isEmpty => Vector(Vector(i))
case (acc, 0) => acc :+ Vector(0)
case (acc, i) => acc.init :+ (acc.last :+ i)
}
where 0 (or whatever) is your delimiter.
Efficient O(n) solution
Tail-recursive solution that never appends anything to lists:
def splitBy[A](sep: A, seq: List[A]): List[List[A]] = {
#annotation.tailrec
def rec(xs: List[A], revAcc: List[List[A]]): List[List[A]] = xs match {
case Nil => revAcc.reverse
case h :: t =>
if (h == sep) {
val (pref, suff) = xs.tail.span(_ != sep)
rec(suff, (h :: pref) :: revAcc)
} else {
val (pref, suff) = xs.span(_ != sep)
rec(suff, pref :: revAcc)
}
}
rec(seq, Nil)
}
val mySeq = List(0, 1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
println(splitBy(0, mySeq))
produces:
List(List(0, 1, 2, 1), List(0, -1), List(0, 1, 2, 3, 2))
It also handles the case where the input does not start with the separator.
For fun: Another O(n) solution that works for small integers
This is more of warning rather than a solution. Trying to reuse String's split does not result in anything sane:
val mySeq = Seq(0, 1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
val z = mySeq.min
val res = (mySeq
.map(x => (x - z).toChar)
.mkString
.split((-z).toChar)
.map(s => 0 :: s.toList.map(_.toInt + z)
).toList.tail)
It will fail if the integers span a range larger than 65535, and it looks pretty insane. Nevertheless, I find it amusing that it works at all:
res: List[List[Int]] = List(List(0, 1, 2, 1), List(0, -1), List(0, 1, 2, 3, 2))
You can use foldLeft:
val delimiter = 0
val res = mySeq.foldLeft(Seq[Seq[Int]]()) {
case (acc, `delimiter`) => acc :+ Seq(delimiter)
case (acc, v) => acc.init :+ (acc.last :+ v)
}
NOTE: This assumes input necessarily starts with delimiter.
One more variant using indices and reverse slicing
scala> val s = Seq(0,1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
s: scala.collection.mutable.Seq[Int] = ArrayBuffer(0, 1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
scala> s.indices.filter( s(_)==0).+:(if(s(0)!=0) -1 else -2).filter(_>= -1 ).reverse.map( {var p=0; x=>{ val y=s.slice(x,s.size-p);p=s.size-x;y}}).reverse
res173: scala.collection.immutable.IndexedSeq[scala.collection.mutable.Seq[Int]] = Vector(ArrayBuffer(0, 1, 2, 1), ArrayBuffer(0, -1), ArrayBuffer(0, 1, 2, 3, 2))
if the starting doesn't have the delimiter, then also it works.. thanks to jrook
scala> val s = Seq(1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
s: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
scala> s.indices.filter( s(_)==0).+:(if(s(0)!=0) -1 else -2).filter(_>= -1 ).reverse.map( {var p=0; x=>{ val y=s.slice(x,s.size-p);p=s.size-x;y}}).reverse
res174: scala.collection.immutable.IndexedSeq[scala.collection.mutable.Seq[Int]] = Vector(ArrayBuffer(1, 2, 1), ArrayBuffer(0, -1), ArrayBuffer(0, 1, 2, 3, 2))
UPDATE1:
More compact version by removing the "reverse" in above
scala> val s = Seq(0,1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
s: scala.collection.mutable.Seq[Int] = ArrayBuffer(0, 1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
scala> s.indices.filter( s(_)==0).+:(if(s(0)!=0) -1 else -2).filter(_>= -1 ).:+(s.size).sliding(2,1).map( x=>s.slice(x(0),x(1)) ).toList
res189: List[scala.collection.mutable.Seq[Int]] = List(ArrayBuffer(0, 1, 2, 1), ArrayBuffer(0, -1), ArrayBuffer(0, 1, 2, 3, 2))
scala> val s = Seq(1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
s: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
scala> s.indices.filter( s(_)==0).+:(if(s(0)!=0) -1 else -2).filter(_>= -1 ).:+(s.size).sliding(2,1).map( x=>s.slice(x(0),x(1)) ).toList
res190: List[scala.collection.mutable.Seq[Int]] = List(ArrayBuffer(1, 2, 1), ArrayBuffer(0, -1), ArrayBuffer(0, 1, 2, 3, 2))
scala>
Here is a solution I believe is both short and should run in O(n):
def seqSplitter[T](s: ArrayBuffer[T], delimiter : T) =
(0 +: s.indices.filter(s(_)==delimiter) :+ s.size) //find split locations
.sliding(2)
.map(idx => s.slice(idx.head, idx.last)) //extract the slice
.dropWhile(_.isEmpty) //take care of the first element
.toList
The idea is to take all the indices where the delimiter occurs, slide over them and slice the sequence at those locations. dropWhile takes care of the first element being a delimiter or not.
Here I am putting all the data in an ArrayBuffer to ensure slicing will take O(size_of_slice).
val mySeq = ArrayBuffer(0, 1, 2, 1, 0, -1, 0, 1, 2, 3, 2)
seqSplitter(mySeq, 0).toList
Gives:
List(ArrayBuffer(0, 1, 2, 1), ArrayBuffer(0, -1), ArrayBuffer(0, 1, 2, 3, 2))
A more detailed complexity analysis
The operations are:
Filter the delimiter indices (O(n))
loop over a list of indices obtained from previous step (O(num_of_delimeters)); for each pair of indices corresponding to a slice:
Copy the slice from the array and put it into the final collection (O(size_of_slice))
The last two steps sum up to O(n).
Related
Generate Adjacency matrix from a Map
I know this is a lengthy question :) I'm trying to implement Hamiltonian Cycle on a dataset in Scala 2.11, as part of this I'm trying to generate Adjacency matrix from a Map of values. Explanation: Keys 0 to 4 are the different cities, so in below "allRoads" Variable 0 -> Set(1, 2) Means city0 is connected to city1 and city2 1 -> Set(0, 2, 3, 4) Means City1 is connected to city0,city2,city3,city4 . . I need to generate adj Matrix, for E.g: I need to generate 1 if the city is connected, or else I've to generate 0, meaning for: "0 -> Set(1, 2)", I need to generate: Map(0 -> Array(0,1,1,0,0)) input- var allRoads = Map(0 -> Set(1, 2), 1 -> Set(0, 2, 3, 4), 2 -> Set(0, 1, 3, 4), 3 -> Set(2, 4, 1), 4 -> Set(2, 3, 1)) My Code: val n: Int = 5 val listOfCities = (0 to n-1).toList var allRoads = Map(0 -> Set(1, 2), 1 -> Set(0, 2, 3, 4), 2 -> Set(0, 1, 3, 4), 3 -> Set(2, 4, 1), 4 -> Set(2, 3, 1)) var adjmat:Array[Int] = Map() for( i <- 0 until allRoads.size;j <- listOfCities) { allRoads.get(i) match { case Some(elem) => if (elem.contains(j)) adjmat = adjmat:+1 else adjmat = adjmat :+0 case _ => None } } which outputs: output: Array[Int] = Array(0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0) Expected output - Something like this, please suggest if there's something better to generate input to Hamiltonian Cycle Map(0 -> Array(0, 1, 1, 0, 0),1 -> Array(1, 0, 1, 1, 1),2 -> Array(1, 1, 0, 1, 1),3 -> Array(0, 1, 1, 0, 1),4 -> Array(0, 1, 1, 1, 0)) Not sure how to store the above output as a Map or a Plain 2D Array.
Try val cities = listOfCities.toSet allRoads.map { case (city, roads) => city -> listOfCities.map(city => if ((cities diff roads).contains(city)) 0 else 1) } which outputs Map(0 -> List(0, 1, 1, 0, 0), 1 -> List(1, 0, 1, 1, 1), 2 -> List(1, 1, 0, 1, 1), 3 -> List(0, 1, 1, 0, 1), 4 -> List(0, 1, 1, 1, 0))
getting list by the first element in the list of lists
Hi I am new to scala and getting silly doubts, I have a list of lists which looks like this (4,List(List(2, 4, 0, 2, 4), List(3, 4, 0, 2, 4), List(4, 0, 1, 2, 4))) I want to get the lists which starts with 4. How to do it.
you use filter to traverse through the List and apply your predicate on each list to check if first elem is 4. example: scala> val (data, options) = (4, List(List(2, 4, 0, 2, 4), List(3, 4, 0, 2, 4), List(4, 0, 1, 2, 4))) data: Int = 4 options: List[List[Int]] = List(List(2, 4, 0, 2, 4), List(3, 4, 0, 2, 4), List(4, 0, 1, 2, 4)) scala> options.filter(_.headOption.contains(data)) res0: List[List[Int]] = List(List(4, 0, 1, 2, 4)) Also see: Scala List.filter with two conditions, applied only once
There are several ways. Here is another listOfLists.collect{ case l # 4 :: _ => l} Potentially more powerful because we can filter on the first n elements, e.g. listOfLists.collect{ case l # 4 :: 0 :: 1 :: _ => l}
If you have a Tuple (Int, List[List[Int]]), and want to return Lists that start with the Int provided in the start, for this case 4: I would recommend you do something like this: val myTuple = (4,List(List(2, 4, 0, 2, 4), List(3, 4, 0, 2, 4), List(4, 0, 1, 2, 4))) myTuple._2.filter(_.headOption.contains(myTuple._1)) And this will return List(List(4, 0, 1, 2, 4)) What we are doing here is, we are first accessing the List[List[Int]] in the Tuple by doing myTuple._2 then we filter to remove Lists that don't have a head value as 4 - which we passed in as myTuple._1. Note we are using headOption instead of head to get the first element in a List, this is to handle exceptions where no List contains the value provided in the start, for this case 4 (more details on this can be found here http://www.bks2.com/blog/2012/12/31/head_vs_headOption/)
val t = (4, List(List(2, 4, 0, 2, 4), List(3, 4, 0, 2, 4), List(4, 0, 1, 2, 4))) t._2.filter(_.head==t._1) In REPL: scala> t._2.filter(_.head==t._1) res5: List[List[Int]] = List(List(4, 0, 1, 2, 4))
Create sublists with elements 1 and 2 in alternate ways in Scala
Hi all I am new with Scala and I have a doubt: Creation of sublists with elements 1 and 2 in alternate ways, never having two consecutive numbers repeated. My function: def functionAlternateElements(list : List[Int]): Option[List[Int]] = { //What should be the solution? } Tests: test("AlternateElementsTests") { assert(ca1.functionAlternateElements(List(1)) === Some(List(1))) assert(ca1.functionAlternateElements(List(1,2)) === Some(List(2))) assert(ca1.functionAlternateElements(List(1,2,3)) === Some(List(1, 2))) assert(ca1.functionAlternateElements(List(1,2,3,4)) === Some(List(1, 2, 1))) assert(ca1.functionAlternateElements(List(1,2,3,4,5)) === Some(List(2, 1, 2))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6)) === Some(List(1, 2, 1, 2))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7)) === Some(List(1, 2, 1, 2, 1))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8)) === Some(List(2, 1, 2, 1, 2))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8,9)) === Some(List(1, 2, 1, 2, 1, 2))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10)) === Some(List(1, 2, 1, 2, 1, 2, 1))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11)) === Some(List(2, 1, 2, 1, 2, 1, 2))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12)) === Some(List(1, 2, 1, 2, 1, 2, 1, 2))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13)) === Some(List(1, 2, 1, 2, 1, 2, 1, 2, 1))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13,14)) === Some(List(2, 1, 2, 1, 2, 1, 2, 1, 2))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)) === Some(List(1, 2, 1, 2, 1, 2, 1, 2, 1, 2))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)) === Some(List(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1))) assert(ca1.functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17)) === Some(List(2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2))) } How can I do this? If you know the code can you give an explanation so I can understand it please?
Given that the assertions seem to be more or less arbitrary, I don't know how to write a program that can produce these strange outputs. However, I know how to write a program that can write a program that can produce these strange outputs. The idea is to generate code that satisfies the requirements. We will generate it by supplying an ansatz and then searching for a bunch of magic numbers by brute-force. First, let's build some infrastructure. We need a tiny framework for solving arbitrary problems by brute force. Here is a trait that is useful for very small problems: trait BruteForce[X] { def engageBruteForceAttack(constraint: X => Boolean): Option[X] def zip[Y](other: BruteForce[Y]): BruteForce[(X, Y)] = new ProductBruteForce[X, Y](this, other) } We need to handle only the finite case and the case of cartesian product: class FiniteBruteForce[X](possibilities: List[X]) extends BruteForce[X] { def engageBruteForceAttack(constraint: X => Boolean) = possibilities.find(constraint) } object FiniteBruteForce { def apply[X](xs: X*) = new FiniteBruteForce[X](xs.toList) } class ProductBruteForce[A, B](a: BruteForce[A], b: BruteForce[B]) extends BruteForce[(A, B)] { def engageBruteForceAttack(constraint: ((A, B)) => Boolean) = { var solution: Option[(A, B)] = None a.engageBruteForceAttack { x => b.engageBruteForceAttack { y => if (constraint((x, y))) { solution = Some((x, y)) true } else { false } }.map(_ => true).getOrElse(false) } solution } } Now we can extract the inputs and outputs from your test cases: val mysteriousTestCases = List( (List(1), List(1)), (List(1,2), List(2)), (List(1,2,3), List(1, 2)), (List(1,2,3,4), List(1, 2, 1)), (List(1,2,3,4,5), List(2, 1, 2)), (List(1,2,3,4,5,6), List(1, 2, 1, 2)), (List(1,2,3,4,5,6,7), List(1, 2, 1, 2, 1)), (List(1,2,3,4,5,6,7,8), List(2, 1, 2, 1, 2)), (List(1,2,3,4,5,6,7,8,9), List(1, 2, 1, 2, 1, 2)), (List(1,2,3,4,5,6,7,8,9,10), List(1, 2, 1, 2, 1, 2, 1)), (List(1,2,3,4,5,6,7,8,9,10,11), List(2, 1, 2, 1, 2, 1, 2)), (List(1,2,3,4,5,6,7,8,9,10,11,12), List(1, 2, 1, 2, 1, 2, 1, 2)), (List(1,2,3,4,5,6,7,8,9,10,11,12,13), List(1, 2, 1, 2, 1, 2, 1, 2, 1)), (List(1,2,3,4,5,6,7,8,9,10,11,12,13,14), List(2, 1, 2, 1, 2, 1, 2, 1, 2)), (List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15), List(1, 2, 1, 2, 1, 2, 1, 2, 1, 2)), (List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16), List(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1)), (List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17), List(2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2)) ) Now let's write a program that will write us the function that computes the strange 1,2,1,1,2,... sequence: val (illuminatiPivot, (illuminatiOffset, illuminatiShift)) = FiniteBruteForce(-1, -2, 0, 1, 2).zip( FiniteBruteForce(-1, -2, 1, 2, 3).zip( FiniteBruteForce(0, 1, 2) ) ).engageBruteForceAttack{ case (p, (o, s)) => mysteriousTestCases.forall { case (input, output) => val (start :: tail) = output val n = input.size val illuminatiNumber = if (n < p) (n + o) else List(1, 1, 2)((n + s) % 3) start == illuminatiNumber } }.get println(s"""|// The function that generates the start number |// of the strange sequences |def illuminatiNumber(n: Int): Int = { | if (n < $illuminatiPivot) (n + $illuminatiOffset) | else List(1, 1, 2)((n + $illuminatiShift) % 3) |} |""".stripMargin) Now do the same for the lengths of the outputs. The ansatz is this time: it should be some affine-linear function that grows with factor 2/3 and is rounded in a weird way: val (hl3ConfirmedConst, hl3ConfirmedOffset) = FiniteBruteForce(-2, -1, 0, 1, 2).zip( FiniteBruteForce(-2, -1, 0, 1, 2, 3) ).engageBruteForceAttack{ case (c, o) => mysteriousTestCases.forall { case (input, output) => val n = input.size val halfLife3Confirmed = c + (n * 2 + o) / 3 output.size == halfLife3Confirmed } }.get println(s"""|def halfLife3Confirmed(i: Int): Int = { | $hl3ConfirmedConst + (i * 2 + $hl3ConfirmedOffset) / 3 |} |""".stripMargin) Finally, I didn't bother to think hard enough how to map 1 to sequence 1,2,1,2,... and 2 to 2,1,2,1,..., so I brute-forced this too: val (tabulationOffset, tabulationShift) = FiniteBruteForce(-1, 0, 1, 2).zip(FiniteBruteForce(0, 1)).engageBruteForceAttack{ case (x, y) => (0 to 2).map(i => x + (y + 1 + i) % 2).toList == List(1, 2, 1) && (0 to 2).map(i => x + (y + 2 + i) % 2).toList == List(2, 1, 2) }.get Now we can write out the initially seeked functionAlternateElements-method: println(s"""|def functionAlternateElements(list : List[Int]): Option[List[Int]] = { | val n = list.size // throw away everything but the size | val resultStart = illuminatiNumber(n) | val resultSize = halfLife3Confirmed(n) | Some(List.tabulate(resultSize){ i => $tabulationOffset + ($tabulationShift + resultStart + i) % 2 }) |} |""".stripMargin) Let's also write out the assertions again: for ((i, o) <- mysteriousTestCases) { val input = i.mkString("List(", ",", ")") val output = o.mkString("List(", ",", ")") println(s"""assert(functionAlternateElements($input) == Some($output))""") } And also let's append a line that tells us that everything went well in the end: println("""println("All assertions are true")""") When run, the above contraption produces the following code: // The function that generates the start number // of the strange sequences def illuminatiNumber(n: Int): Int = { if (n < -1) (n + -1) else List(1, 1, 2)((n + 0) % 3) } def halfLife3Confirmed(i: Int): Int = { 0 + (i * 2 + 1) / 3 } def functionAlternateElements(list : List[Int]): Option[List[Int]] = { val n = list.size // throw away everything but the size val resultStart = illuminatiNumber(n) val resultSize = halfLife3Confirmed(n) Some(List.tabulate(resultSize){ i => 1 + (1 + resultStart + i) % 2 }) } assert(functionAlternateElements(List(1)) == Some(List(1))) assert(functionAlternateElements(List(1,2)) == Some(List(2))) assert(functionAlternateElements(List(1,2,3)) == Some(List(1,2))) assert(functionAlternateElements(List(1,2,3,4)) == Some(List(1,2,1))) assert(functionAlternateElements(List(1,2,3,4,5)) == Some(List(2,1,2))) assert(functionAlternateElements(List(1,2,3,4,5,6)) == Some(List(1,2,1,2))) assert(functionAlternateElements(List(1,2,3,4,5,6,7)) == Some(List(1,2,1,2,1))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8)) == Some(List(2,1,2,1,2))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8,9)) == Some(List(1,2,1,2,1,2))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10)) == Some(List(1,2,1,2,1,2,1))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11)) == Some(List(2,1,2,1,2,1,2))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12)) == Some(List(1,2,1,2,1,2,1,2))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13)) == Some(List(1,2,1,2,1,2,1,2,1))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13,14)) == Some(List(2,1,2,1,2,1,2,1,2))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)) == Some(List(1,2,1,2,1,2,1,2,1,2))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)) == Some(List(1,2,1,2,1,2,1,2,1,2,1))) assert(functionAlternateElements(List(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17)) == Some(List(2,1,2,1,2,1,2,1,2,1,2))) println("All assertions are true") When we execute the generated code, we get only: All assertions are true and no AssertionErrors. Thus, we've managed to implement the strange function successfully. Tip of the day: you know that your specification is bad when the only way to satisfy the tests is by brute-forcing a bunch of magic numbers.
Split a list into multiple lists with String and Integers
I have an input like below: List("aabc", 3, 1, 2, 1, "vwxyz", 2, 3, 4, "sdsafw", 4, 1, 2, 22, 4) And I would like to split it as follows: List(List(“aabc”, 3, 1, 2, 1), List(“vwxyz”, 2, 3, 4), List(“sdsafw”, 4, 1, 2, 22, 4)) or List(List(“aabc”, 1, 2, 1), List(“vwxyz”, 3, 4), List(“sdsafw”, 1, 2, 22, 4)) (The number right after each “String” actually indicates how many integers come after itself. And if it can be done nicely, I would like to remove it at this point.) Would you tell me how I can do this?
If you have a List as val list = List("aabc", 3, 1, 2, 1, "vwxyz", 2, 3, 4, "sdsafw", 4, 1, 2, 22, 4) Then you can write a recursive function as def splitList(list: List[Any], tempList: List[Any], listBuffer: ListBuffer[List[Any]]): ListBuffer[List[Any]] = list match { case x :: y => if(tempList.isEmpty){ splitList(y, List(x), listBuffer) } else { splitList(y.drop(x.asInstanceOf[Int]), List.empty, listBuffer += tempList ++ List(x) ++ y.take(x.asInstanceOf[Int])) } case Nil => listBuffer } Calling this function println(splitList(list, List.empty, ListBuffer.empty[List[Any]])) would give you your desired output ListBuffer(List(aabc, 3, 1, 2, 1), List(vwxyz, 2, 3, 4), List(sdsafw, 4, 1, 2, 22, 4)) You can manipulate the desired output with ListBuffer or Array or List according to your need. Yet Another form of your solution can be using following recursive function. def splitList(list: List[Any], tempList: List[Any], listBuffer: ListBuffer[List[Any]]): ListBuffer[List[Any]] = list match { case x :: y => if (x.isInstanceOf[String]) { if(!tempList.isEmpty){ splitList(y, List(x), listBuffer += tempList) } else { splitList(y, List(x), listBuffer) } }else splitList(y, tempList ++ List(x), listBuffer) case Nil => listBuffer += tempList }
Array initializing in Scala
I'm new to Scala ,just started learning it today.I would like to know how to initialize an array in Scala. Example Java code String[] arr = { "Hello", "World" }; What is the equivalent of the above code in Scala ?
scala> val arr = Array("Hello","World") arr: Array[java.lang.String] = Array(Hello, World)
To initialize an array filled with zeros, you can use: > Array.fill[Byte](5)(0) Array(0, 0, 0, 0, 0) This is equivalent to Java's new byte[5].
Can also do more dynamic inits with fill, e.g. Array.fill(10){scala.util.Random.nextInt(5)} ==> Array[Int] = Array(0, 1, 0, 0, 3, 2, 4, 1, 4, 3)
Additional to Vasil's answer: If you have the values given as a Scala collection, you can write val list = List(1,2,3,4,5) val arr = Array[Int](list:_*) println(arr.mkString) But usually the toArray method is more handy: val list = List(1,2,3,4,5) val arr = list.toArray println(arr.mkString)
If you know Array's length but you don't know its content, you can use val length = 5 val temp = Array.ofDim[String](length) If you want to have two dimensions array but you don't know its content, you can use val row = 5 val column = 3 val temp = Array.ofDim[String](row, column) Of course, you can change String to other type. If you already know its content, you can use val temp = Array("a", "b")
Another way of declaring multi-dimentional arrays: Array.fill(4,3)("") res3: Array[Array[String]] = Array(Array("", "", ""), Array("", "", ""),Array("", "", ""), Array("", "", ""))
[Consolidating all the answers] Initializing 1-D Arrays // With fixed values val arr = Array("a", "ab", "c") // With zero value of the type val size = 13 val arrWithZeroVal = Array.ofDim[Int](size) //values = 0 val arrBoolWithZeroVal = Array.ofDim[Boolean](size) //values = false // With default value val defVal = -1 val arrWithDefVals = Array.fill[Int](size)(defVal) //With random values val rand = scala.util.Random def randomNumberGen: Int = rand.nextInt(5) val arrWithRandomVals = Array.fill[Int](size){randomNumberGen} Initializing 2-D/3-D/n-D Arrays // With zero value of the type val arr3dWithZeroVal = Array.ofDim[Int](5, 4, 3) // With default value val defVal = -1 val arr3dWithDefVal = Array.fill[Int](5, 4, 3)(defVal) //With random values val arr3dWithRandomValv = Array.fill[Int](5, 4, 3){randomNumberGen} Conclusion : Use Array.ofDim[TYPE](d1, d2, d3...) to use zero value of the type. Use Array.fill[TYPE](d1, d2, d3...)(functionWhichReturnsTYPE) otherwise Output for reference : scala> val arr = Array("a", "ab", "c") arr: Array[String] = Array(a, ab, c) scala> val size = 13 size: Int = 13 scala> val arrWithZeroVal = Array.ofDim[Int](size) //values = 0 arrWithZeroVal: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) scala> val arrBoolWithZeroVal = Array.ofDim[Boolean](size) //values = false arrBoolWithZeroVal: Array[Boolean] = Array(false, false, false, false, false, false, false, false, false, false, false, false, false) scala> val defVal = -1 defVal: Int = -1 scala> val arrWithDefVals = Array.fill[Int](size)(defVal) arrWithDefVals: Array[Int] = Array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1) scala> val rand = scala.util.Random rand: util.Random.type = scala.util.Random$#6e3dd5ce scala> def randomNumberGen: Int = rand.nextInt(5) randomNumberGen: Int scala> val arrWithRandomVals = Array.fill[Int](size){randomNumberGen} arrWithRandomVals: Array[Int] = Array(2, 2, 3, 1, 1, 3, 3, 3, 2, 3, 2, 2, 0) scala> val arr3dWithZeroVal = Array.ofDim[Int](5, 4, 3) arr3dWithZeroVal: Array[Array[Array[Int]]] = Array(Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0)), Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0)), Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0)), Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0)), Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0))) scala> val arr3dWithDefVal = Array.fill[Int](5, 4, 3)(defVal) arr3dWithDefVal: Array[Array[Array[Int]]] = Array(Array(Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1)), Array(Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1)), Array(Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1)), Array(Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1)), Array(Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1), Array(-1, -1, -1))) scala> val arr3dWithRandomVals = Array.fill[Int](5, 4, 3){randomNumberGen} arr3dWithRandomVals: Array[Array[Array[Int]]] = Array(Array(Array(2, 0, 0), Array(4, 1, 0), Array(4, 0, 0), Array(0, 0, 1)), Array(Array(0, 1, 2), Array(2, 0, 2), Array(0, 4, 2), Array(0, 4, 2)), Array(Array(4, 3, 0), Array(2, 2, 4), Array(4, 0, 4), Array(4, 2, 1)), Array(Array(0, 3, 3), Array(0, 0, 4), Array(4, 1, 3), Array(2, 2, 3)), Array(Array(0, 2, 3), Array(1, 4, 1), Array(1, 3, 3), Array(0, 0, 3)))