2013-07-13 12 views
25

Mam problem z podstawową operacją Scala i to doprowadza mnie do szału.Drukowanie tablicy w Scali

val a = Array(1,2,3) 

println(a) and result is [[email protected] 

println(a.toString()) and result is [[email protected] 

println(a.toString) and result is [[email protected] 

Czy ktoś może mi powiedzieć, jak wydrukować tablicę bez pisania własnej funkcji, ponieważ to jest głupie. Dzięki!

+0

Spróbuj podobnego kodu w Javie, a zobaczysz, że robi to samo. 'T []. ToString()' nie zwraca 'String' zawierającego elementy tablicy. – Jashaszun

+0

Jestem trochę zardzewiały w java: D ... więc, mówisz, że nie ma rozwiązania do drukowania tablicy, ale funkcja pisania samodzielnie? ... –

+0

dupe http://stackoverflow.com/questions/3328085/scala-printing-arrays i inne –

Odpowiedz

55

mkString będzie konwertować kolekcje (w tym Array) element po elemencie na reprezentacje ciągów.

println(a.mkString(" ")) 

to prawdopodobnie to, czego potrzebujesz.

+1

Tak, to zdecydowanie lepsze rozwiązanie .. – Hassan

+0

to jest to! ... bardzo dziękuję :) ... Wiedziałem, że musi być jakieś normalne rozwiązanie. –

2

Jeśli używasz lista zamiast toString() metoda drukuje rzeczywiste elenents (a nie hashCode)

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

lub

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

Można zrobić normalną rzeczą (patrz też Rex lub Jiri za odpowiedź) lub możesz:

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

Hej, nie fair! REPL wydrukował to naprawdę dobrze.

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

Nie radość, dopóki:

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) 
" 

Zastanawiam się, czy istnieje ustawienie szerokości w REPL. Aktualizacja: nie ma. Jest ustalona na

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

Ale nie będę próbować miliardy:

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 

Czekaj, zróbmy to:

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

Może to być oczywiste:

scala> var vs = List("1") 
vs: List[String] = List(1) 

scala> vs = null 
vs: List[String] = null 

scala> vs.mkString 
java.lang.NullPointerException 

Zamiast tego:

scala> import runtime.ScalaRunTime.stringOf 
import runtime.ScalaRunTime.stringOf 

scala> stringOf(vs) 
res16: String = null 

Również tablica nie musi być głębokie, aby korzystać z jego stringPrefix:

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

Niezależnie od wybranej metody wolisz, można owinąć go:

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) 
    } 
} 

Ale tablice będzie wymagać specjalnej konwersji, ponieważ nie dostaniesz 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 
1

Zamiast ręcznie samodzielnie określać wszystkie parametry dla mkString (co jest nieco bardziej szczegółowe, jeśli chcesz dodać znaczniki początkowe i końcowe oprócz ogranicznika), możesz skorzystać z klasy WrappedArray, which uses mkString internally.W przeciwieństwie do konwertowania tablicy na List lub inną strukturę danych, klasa WrappedArray po prostu opakowuje odniesienie do tablicy, jest tworzona w efektywnie stałym czasie.

scala> val a = Array.range(1, 10)     
a: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) 

scala> println(a)        
[[email protected]          

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)   
6

Oto dwie metody.

Jednym z nich jest użycie foreach:

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

Drugim jest użycie mkString:

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

Dla każdej lepszej odpowiedzi dla dużej tablicy. – tgkprog

0

Na prostą tablicę Ints jak to możemy przekonwertować do Scala Listę (scala.collection.immutable.List) a następnie użyj 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) 

Jeśli możesz wcześniej przekonwertować na listę i wykonywać wszystkie operacje na listach, to prawdopodobnie skończysz pisać bardziej idiomatyczną Scalę, napisaną w stylu funkcjonalnym.

Należy zauważyć, że za pomocą List.fromArray jest przestarzała (a została usunięta 2.12.2).

0

Metoda deep w ArrayLike rekurencyjnie konwertuje wielowymiarowe tablice na WrappedArray i zastępuje długi prefiks "WrappedArray" za pomocą "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" 
} 

Zastosowanie:

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))