Converting immutable to mutable collections - scala

What is the best way to convert collection.immutable.Set to collection.mutable.Set?

scala> var a=collection.mutable.Set[Int](1,2,3)
a: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala> var b=collection.immutable.Set[Int](1,2,3)
b: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> collection.mutable.Set(b.toArray:_*)
res0: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala> collection.mutable.Set(b.toSeq:_*)
res1: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala> collection.mutable.Set(b.toList:_*)
res2: scala.collection.mutable.Set[Int] = Set(1, 2, 3)

Starting Scala 2.13, via factory builders applied with .to(factory):
Set(1, 2, 3).to(collection.mutable.Set)
// collection.mutable.Set[Int] = HashSet(1, 2, 3)
Prior to Scala 2.13 and starting Scala 2.10:
Set(1, 2, 3).to[collection.mutable.Set]
// collection.mutable.Set[Int] = Set(1, 2, 3)

Related

What is the non-flattened Scala Vector of Sets: (1 to 2).flatMap((1 to 3).toSet.subsets(_))?

I can see (1 to 2) is a Range.
scala> (1 to 2)
res20: scala.collection.immutable.Range.Inclusive = Range(1, 2)
I can see the Sets from this Iterator.
scala> (1 to 3).toSet.subsets
res0: Iterator[scala.collection.immutable.Set[Int]] = non-empty iterator
scala> (1 to 3).toSet.subsets.mkString("\n")
res1: String =
Set()
Set(1)
Set(2)
Set(3)
Set(1, 2)
Set(1, 3)
Set(2, 3)
Set(1, 2, 3)
Finally, here is a Vector of Sets when flattened. What is it when not flatted? How can I display it?
scala> (1 to 2).flatMap((1 to 3).toSet.subsets(_))
res19: scala.collection.immutable.IndexedSeq[scala.collection.immutable.Set[Int]] = Vector(Set(1), Set(2), Set(3), Set(1, 2), Set(1, 3), Set(2, 3))
Replacing flatMap with map would give an unflattened list of subsets of different sizes:
(1 to 2).map((1 to 3).toSet.subsets(_).toVector)
// res1: scala.collection.immutable.IndexedSeq[Vector[scala.collection.immutable.Set[Int]]] = Vector(
// Vector(Set(1), Set(2), Set(3)),
// Vector(Set(1, 2), Set(1, 3), Set(2, 3))
// )
Note that since subsets returns an Iterator[Set[A]], toVector converts the Iterators into nested Vectors.

Scala difference between (1 to 4).toSet and (1 to 4).to[scala.collection.immutable.Set]?

Scala difference between (1 to 4).to[scala.collection.immutable.Set] and (1 to 4).toSet?
scala> (1 to 4).toSet
res37: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)
scala> (1 to 4).to[scala.collection.immutable.Set]
res38: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)
scala> (1 to 4).to[Set]
res39: Set[Int] = Set(1, 2, 3, 4)
scala> Set(1 to 4:_*)
res14: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)
If you look at the implementation of toSet:
def toSet[B >: A]: immutable.Set[B] = to[immutable.Set].asInstanceOf[immutable.Set[B]]
you can see it's just an alias to to[]. So it's the same.
Note that from Scala 2.13 and up, it's to(Set). See doc and release note
They should all be the same, Set is just an alias like so
type Set[A] = immutable.Set[A]

Scala .init method example

Can you please explain what init method performs with respect to below list
i can see the result of new list says that last sequence is being omitted from the existing list.
val numbers = List(1, 2, 3, 4, 5)
val result = numbers.init
println(result)
.init and .last are the compliments to the .head and .tail methods.
val nums = List(1,2,3,4)
nums.head //res0: Int = 1
nums.tail //res1: List[Int] = List(2, 3, 4)
nums.init //res2: List[Int] = List(1, 2, 3)
nums.last //res3: Int = 4
def init: List[A] which selects all elements except the last.
l: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8)
scala> l.last
res58: Int = 8
scala> l.init
res59: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
scala> val testList = List(1,2,3,4,5)
testList: List[Int] = List(1, 2, 3, 4, 5)
scala> testList.init
res0: List[Int] = List(1, 2, 3, 4)
scala> testList.last
res1: Int = 5
scala> testList.head
res2: Int = 1
scala> testList.tail
res3: List[Int] = List(2, 3, 4, 5)

takeWhile: also need first element failed the condition in scala

scala> List(1,2,3,4,5,6,7).takeWhile(i=>i<5)
res1: List[Int] = List(1, 2, 3, 4)
What if I also need to include 5 in the result?
Assuming that the function that you will be using is more complicated than the taking first 5 elements then,
You can do
scala> List(1,2,3,4,5,6,7)
res5: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
scala> res5.takeWhile(_<5) ++ res5.dropWhile(_<5).take(1)
res7: List[Int] = List(1, 2, 3, 4, 5)
Also
scala> res5.span(_<5)
res8: (List[Int], List[Int]) = (List(1, 2, 3, 4),List(5, 6, 7))
scala> res8._1 ++ res8._2.take(1)
res10: List[Int] = List(1, 2, 3, 4, 5)
Also
scala> res5.take(res5.segmentLength(_<5, 0) + 1)
res17: List[Int] = List(1, 2, 3, 4, 5)
scala> res5.take(res5.indexWhere(_>5))
res18: List[Int] = List(1, 2, 3, 4, 5)
Edit
If this is not a parallelized computation and you won't be using the parallel collections:
var last = myList.head
val rem = myList.takeWhile{ x=>
last = x
x < 5
}
last :: rem
anonymous function forming a closure around the solution you want.
Previous Answer
I'd settle for the far less complicated:
.takeWhile(_ <= 5)
wherein you're just using the less than or equal operator.
List(1,2,3,4,5,6,7,8).takeWhile(_ <= 5)
This is best optimal solution for it

Prepending Items to Scala Set

In Scala I can prepend items to a List via:
scala> 1 :: 2 :: 3 :: Nil
res16: List[Int] = List(1, 2, 3)
What's the equivalent :: operator for a Scala Set?
I believe you're looking for +. It's not called "prepend", but "add". The reason is that Set doesn't guarantee an ordering for the inserted elements.
scala> val s = Set(1, 2, 3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> s + 3
res0: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> s + 4
res1: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)
scala> s + 4 + 5
res2: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)