Impresión de matriz en Scala

Estoy teniendo problemas con la mayoría de las operaciones básicas de Scala y me está volviendo loco.

val a = Array(1,2,3) println(a) and result is [I@1e76345 println(a.toString()) and result is [I@1e76345 println(a.toString) and result is [I@1e76345 

¿Alguien puede decirme cómo imprimir matriz sin escribir mi propia función para hacer eso porque es una tontería? ¡Gracias!

mkString convertirá las colecciones (incluida la Array ) elemento por elemento en representaciones de cadenas.

 println(a.mkString(" ")) 

es probablemente lo que quieres

Puedes hacer lo normal (ver la respuesta de Rex o Jiri) o puedes:

 scala> Array("bob","sue") res0: Array[String] = Array(bob, sue) 

Oye, no es justo! El REPL lo imprimió muy bien.

 scala> res0.toString res1: String = [Ljava.lang.String;@63c58252 

Sin alegría, hasta que:

 scala> runtime.ScalaRunTime.stringOf(res0) res2: String = Array(bob, sue) scala> runtime.ScalaRunTime.replStringOf(res0, res0.length) res3: String = "Array(bob, sue) " scala> runtime.ScalaRunTime.replStringOf(res0, 1) res4: String = "Array(bob) " 

Me pregunto si hay una configuración de ancho en el REPL. Actualización: no hay. Está arreglado en

 val maxStringElements = 1000 // no need to mkString billions of elements 

Pero no probaré miles de millones:

 scala> Array.tabulate(100)(identity) res5: Array[Int] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99) scala> import runtime.ScalaRunTime.replStringOf import runtime.ScalaRunTime.replStringOf scala> replStringOf(res5, 10) res6: String = "Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) " scala> res5.take(10).mkString(", ") res7: String = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 

Espera, hagámoslo:

 scala> res5.take(10).mkString("Array(", ", ", ")") res8: String = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 

Esto podría ser obvio:

 scala> var vs = List("1") vs: List[String] = List(1) scala> vs = null vs: List[String] = null scala> vs.mkString java.lang.NullPointerException 

Así que en vez:

 scala> import runtime.ScalaRunTime.stringOf import runtime.ScalaRunTime.stringOf scala> stringOf(vs) res16: String = null 

Además, una matriz no necesita ser profunda para beneficiarse de su stringPrefix:

 scala> println(res0.deep.toString) Array(bob, sue) 

Cualquiera que sea el método que prefiera, puede resumirlo:

 implicit class MkLines(val t: TraversableOnce[_]) extends AnyVal { def mkLines: String = t.mkString("", EOL, EOL) def mkLines(header: String, indented: Boolean = false, embraced: Boolean = false): String = { val space = "\u0020" val sep = if (indented) EOL + space * 2 else EOL val (lbrace, rbrace) = if (embraced) (space + "{", EOL + "}") else ("", "") t.mkString(header + lbrace + sep, sep, rbrace + EOL) } } 

Pero las matrices necesitarán una conversión especial porque no obtienes ArrayOps:

 implicit class MkArrayLines(val a: Array[_]) extends AnyVal { def asTO: TraversableOnce[_] = a def mkLines: String = asTO.mkLines def mkLines(header: String = "Array", indented: Boolean = false, embraced: Boolean = false): String = asTO.mkLines(header, indented, embraced) } scala> Console println Array("bob","sue","zeke").mkLines(indented = true) Array bob sue zeke 

Aquí hay dos métodos.

Una es usar foreach :

 val a = Array(1,2,3) a.foreach(println) 

El otro es usar mkString :

 val a = Array(1,2,3) println(a.mkString("")) 

Si usa la lista en su lugar, el método toString() imprime los elementos reales (no el código hash)

 var a = List(1,2,3) println(a) 

o

 var a = Array(1,2,3) println(a.toList) 

En lugar de especificar manualmente todos los parámetros para mkString (que es un poco más detallado si desea agregar marcadores de inicio y final además del delimitador), puede aprovechar la clase WrappedArray , que usa mkString internamente . A diferencia de la conversión de la matriz a una List o alguna otra estructura de datos, la clase WrappedArray simplemente envuelve una referencia de matriz, se crea en tiempo efectivamente constante.

 scala> val a = Array.range(1, 10) a: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) scala> println(a) [I@64a2e69d scala> println(x: Seq[_]) // implicit WrappedArray(a, b, c, d) scala> println(a.toSeq) // explicit WrappedArray(1, 2, 3, 4, 5, 6, 7, 8, 9) 

Para una matriz simple de Ints como esta, podemos convertirla en una lista de Scala ( scala.collection.immutable.List ) y luego usar List.toString() :

 var xs = Array(3,5,9,10,2,1) println(xs.toList.toString) // => List(3, 5, 9, 10, 2, 1) println(xs.toList) // => List(3, 5, 9, 10, 2, 1) 

Si puede convertir a una Lista más temprano y hacer todas sus operaciones con Listas, entonces probablemente termine escribiendo Scala más idiomático, escrito en un estilo funcional.

Tenga en cuenta que el uso de List.fromArray está en desuso (y se ha eliminado en 2.12.2) .

El método en deep en ArrayLike convierte recursivamente matrices multidimensionales en WrappedArray , y sobrescribe un prefijo largo “WrappedArray” con “Array”.

 def deep: scala.collection.IndexedSeq[Any] = new scala.collection.AbstractSeq[Any] with scala.collection.IndexedSeq[Any] { def length = self.length def apply(idx: Int): Any = self.apply(idx) match { case x: AnyRef if x.getClass.isArray => WrappedArray.make(x).deep case x => x } override def stringPrefix = "Array" } 

Uso:

 scala> val arr = Array(Array(1,2,3),Array(4,5,6)) arr: Array[Array[Int]] = Array(Array(1, 2, 3), Array(4, 5, 6)) scala> println(arr.deep) Array(Array(1, 2, 3), Array(4, 5, 6))