Convert an array to a mutable set in Scala? - scala

How does one convert a Scala Array to a mutable.Set?
It's easy to convert to an immutable.Set:
Array(1, 2, 3).toSet
But I can't find an obvious way to convert to a mutable.Set.

scala> val s=scala.collection.mutable.Set()++Array(1,2,3)
s: scala.collection.mutable.Set[Int] = Set(2, 1, 3)

scala> scala.collection.mutable.Set( Array(1,2) :_* )
res2: scala.collection.mutable.Set[Int] = Set(2, 1)
The weird :_* type ascription, forces factory method to see the array as a list of arguments.

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

Related

Convert List[Any] to List[Int]

How can I convert
List(1, 2, "3")
to
List(1, 2, 3)
since List(1, 2, "3") is of type List[Any] and I can't use .toInt on Any.
That should be sufficient solution:
l.map(_.toString.toInt)
Starting Scala 2.13 and the introduction of String#toIntOption, we can make #liosedhel's answer a bit safer if needs be:
// val l: List[Any] = List(1, 2, "3")
l.flatMap(_.toString.toIntOption)
// List[Int] = List(1, 2, 3)

Why does List.toString and Vector.toString return a nice representation but not Array.toString?

scala> Array(1, 2, 3).toString
res1: String = [I#11cf437c
scala> List(1, 2, 3).toString
res2: String = List(1, 2, 3)
scala> Vector(1, 2, 3).toString
res3: String = Vector(1, 2, 3)
Logically, one would expect Array(1, 2, 3).toString to return "Array(1, 2, 3)".
Update: seems to me like Array maps to the built in Java array type—is this correct? and if yes, is this the reason Array.toString has to behave like this?
It is because Array is a Java object. You can however use runtime.ScalaRunTime.stringOf if it suits your needs.
scala> runtime.ScalaRunTime.stringOf(Array(1, 2, 3))
res3: String = Array(1, 2, 3)
scala> List(1,2,3).getClass()
res0: Class[_ <: List[Int]] = class scala.collection.immutable.$colon$colon
scala> Vector(1,2,3).getClass()
res1: Class[_ <: scala.collection.immutable.Vector[Int]] = class scala.collection.immutable.Vector
scala> Array(1,2,3).getClass()
res2: Class[_ <: Array[Int]] = class [I
List and Vector are Scala classes, so they have a nice representation. Array comes from Java and practices Java's ugliness.

Scala convert Iterable or collection.Seq to collection.immutable.Seq

It appears the toSeq method in Scala collections returns a scala.collection.Seq, I could also return a Traversable or Iterable but need to convert this to a scala.collection.immutable.Seq.
Is there an easy way to do this?
Thanks
Richard
Use the to method to convert between arbitrary collection types in Scala 2.10:
scala> Array(1, 2, 3).toSeq
res0: Seq[Int] = WrappedArray(1, 2, 3)
scala> Array(1, 2, 3).to[collection.immutable.Seq]
res1: scala.collection.immutable.Seq[Int] = Vector(1, 2, 3)

Convert Seq to ArrayBuffer

Is there any concise way to convert a Seq into ArrayBuffer in Scala?
scala> val seq = 1::2::3::Nil
seq: List[Int] = List(1, 2, 3)
scala> seq.toBuffer
res2: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3)
EDIT After Scala 2.1x, there is a method .to[Coll] defined in TraversableLike, which can be used as follow:
scala> import collection.mutable
import collection.mutable
scala> seq.to[mutable.ArrayBuffer]
res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
scala> seq.to[mutable.Set]
res2: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
This will work:
ArrayBuffer(mySeq : _*)
Some explanations: this uses the apply method in the ArrayBuffer companion object. The signature of that method is
def apply [A] (elems: A*): ArrayBuffer[A]
meaning that it takes a variable number of arguments. For instance:
ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8)
is also a valid call. The ascription : _* indicates to the compiler that a Seq should be used in place of that variable number of arguments (see Section 4.6.2 in the Scala Reference).

Converting immutable to mutable collections

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)