2011-09-24 18 views
11

को कंसोल करने के लिए तालिका बनाएं मुझे कंसोल में एक टेबल प्रदर्शित करने की आवश्यकता है।स्कैला:

मेरे सरल उपाय, यदि आप इसे एक "समाधान" कहेंगे, इस प्रकार है:

override def toString() = { 
    var res = "\n" 
     var counter = 1; 
     res += stateDb._1 + "\n" 
     res += " +----------------------------+\n" 
     res += " +  State Table   +\n" 
     res += " +----------------------------+\n" 
     for (entry <- stateDb._2) { 
     res += " | " + counter + "\t | " + entry._1 + " | " + entry._2 + " |\n" 
     counter += 1; 
     } 
     res += " +----------------------------+\n" 
     res += "\n" 
    res 

    } 

हम इस

  • बहस करने की जरूरत नहीं है एक बुरा लग रही है जब
  • दिखाया गया है
  • ख कोड थोड़े

वास्तव में गड़बड़ लग रही है, इस तरह के एक प्रश्न सी # के लिए कहा गया था, लेकिन मैं चाहूँगा स्कैला के लिए भी एक अच्छा समाधान जानने के लिए।

तो स्केल में स्केल में ऐसी तालिका खींचने के लिए (अच्छा/अच्छा/सरल/जो भी) तरीका क्या है?

------------------------------------------------------------------------- 
| Column 1  | Column 2  | Column 3  | Column 4  | 
------------------------------------------------------------------------- 
|     |     |     |     | 
|     |     |     |     | 
|     |     |     |     | 
------------------------------------------------------------------------- 

उत्तर

24

मैं अपने वर्तमान परियोजना से निम्नलिखित खींच लिया गया है:

object Tabulator { 
    def format(table: Seq[Seq[Any]]) = table match { 
    case Seq() => "" 
    case _ => 
     val sizes = for (row <- table) yield (for (cell <- row) yield if (cell == null) 0 else cell.toString.length) 
     val colSizes = for (col <- sizes.transpose) yield col.max 
     val rows = for (row <- table) yield formatRow(row, colSizes) 
     formatRows(rowSeparator(colSizes), rows) 
    } 

    def formatRows(rowSeparator: String, rows: Seq[String]): String = (
    rowSeparator :: 
    rows.head :: 
    rowSeparator :: 
    rows.tail.toList ::: 
    rowSeparator :: 
    List()).mkString("\n") 

    def formatRow(row: Seq[Any], colSizes: Seq[Int]) = { 
    val cells = (for ((item, size) <- row.zip(colSizes)) yield if (size == 0) "" else ("%" + size + "s").format(item)) 
    cells.mkString("|", "|", "|") 
    } 

    def rowSeparator(colSizes: Seq[Int]) = colSizes map { "-" * _ } mkString("+", "+", "+") 
} 

scala> Tabulator.format(List(List("head1", "head2", "head3"), List("one", "two", "three"), List("four", "five", "six"))) 
res1: java.lang.String = 
+-----+-----+-----+ 
|head1|head2|head3| 
+-----+-----+-----+ 
| one| two|three| 
| four| five| six| 
+-----+-----+-----+ 
+0

यह सुंदर है। कोशिश की और मैं वही था जो मैं खोज रहा था। – evildead

+4

एक अतिरिक्त के रूप में यह संरेखण छोड़ दिया गया है ("%" + आकार + "एस")। प्रारूप (आइटम) यह दाएं ("% -" + आकार + "एस")। प्रारूप (आइटम) – evildead

+1

एक अच्छा के रूप में भी अच्छा होगा 'अंतर्निहित वर्ग 'जो कि जोड़ता है उदाहरण के लिए '.asTable' 'सेक [सेक [कोई]]' :) –

2

इसे टोकननाइज़ करें। मैं कुछ मामले वस्तुओं और वर्गों बनाने को देख के साथ शुरू होता है, ताकि आप एक tokenized सूची जो प्रदर्शन प्रयोजनों के लिए पर संचालित किया जा सकता उत्पादन: तो फिर तुम पंक्ति वस्तु के कुछ प्रकार के साथ कुछ शर्तों के फार्म कर सकते हैं

sealed trait TableTokens{ 
    val width: Int 
} 
case class Entry(value: String) extends TableTokens{ 
    val width = value.length 
} 
case object LineBreak extends TableTokens{ 
    val width = 0 
} 
case object Div extends TableTokens{ 
    val width = 1 
} 

:

case class Row(contents: List[TableTokens]) extends TableTokens{ 
    val width = contents.foldLeft(0)((x,y) => x = y.width) 
} 

फिर आप एक अपरिवर्तनीय फैशन में ऐसी चीजों और चीजों की जांच कर सकते हैं। शायद जोड़कर टेबल और संरेखण के लिए तरीके बनाने ...

case class Table(contents: List[TableTokens]) 

इसका मतलब है कि आप तालिकाओं के कई अलग-अलग रूपों हो सकता था जहां अपनी शैली अपने संरचना, एक ला HTML और सीएसएस से अलग है।

+0

शायद आप एक छोटा सा उदाहरण जोड़ सकते हैं। मैं इसे पूरी तरह से नहीं मिल रहा हूँ। – evildead

+0

मैं दूसरा @ evildead- अगर किसी मौजूदा अनुक्रम को प्रस्तुत करने के बारे में कुछ भी टोकननाइज़ किया जाए? –

2

टन टेबुलेटर कोड के लिए धन्यवाद की!

स्पार्क डेटासेट टैब्यूलर प्रिंटिंग के लिए एक संशोधन है।

मेरा मतलब है आप DataFrame सामग्री या खींचा परिणाम सेट मुद्रित कर सकते हैं की तरह

Tabulator(hiveContext.sql("SELECT * FROM stat")) 
Tabulator(hiveContext.sql("SELECT * FROM stat").take(20)) 

, दूसरा एक निश्चित रूप से शीर्ष लेख के बिना हो जाएगा, DF कार्यान्वयन के लिए आप सेट कर सकते हैं कि कितने पंक्तियों स्पार्क डेटा फ्रेम से खींचने के लिए प्रिंटिंग और आपको हेडर की आवश्यकता है या नहीं।

/** 
* Tabular representation of Spark dataset. 
* Usage: 
* 1. Import source to spark-shell: 
* spark-shell.cmd --master local[2] --packages com.databricks:spark-csv_2.10:1.3.0 -i /path/to/Tabulator.scala 
* 2. Tabulator usage: 
* import org.apache.spark.sql.hive.HiveContext 
* val hiveContext = new HiveContext(sc) 
* val stat = hiveContext.read.format("com.databricks.spark.csv").option("header", "true").option("inferSchema", "true").option("delimiter", "\t").load("D:\\data\\stats-belablotski.tsv") 
* stat.registerTempTable("stat") 
* Tabulator(hiveContext.sql("SELECT * FROM stat").take(20)) 
* Tabulator(hiveContext.sql("SELECT * FROM stat")) 
*/ 
object Tabulator { 

    def format(table: Seq[Seq[Any]], isHeaderNeeded: Boolean) : String = table match { 
    case Seq() => "" 
    case _ => 
     val sizes = for (row <- table) yield (for (cell <- row) yield if (cell == null) 0 else cell.toString.length) 
     val colSizes = for (col <- sizes.transpose) yield col.max 
     val rows = for (row <- table) yield formatRow(row, colSizes) 
     formatRows(rowSeparator(colSizes), rows, isHeaderNeeded) 
    } 

    def formatRes(table: Array[org.apache.spark.sql.Row]): String = { 
    val res: Seq[Seq[Any]] = (for { r <- table } yield r.toSeq).toSeq 
    format(res, false) 
    } 

    def formatDf(df: org.apache.spark.sql.DataFrame, n: Int = 20, isHeaderNeeded: Boolean = true): String = { 
    val res: Seq[Seq[Any]] = (for { r <- df.take(n) } yield r.toSeq).toSeq 
    format(List(df.schema.map(_.name).toSeq) ++ res, isHeaderNeeded) 
    } 

    def apply(table: Array[org.apache.spark.sql.Row]): Unit = 
    println(formatRes(table)) 

    /** 
    * Print DataFrame in a formatted manner. 
    * @param df Data frame 
    * @param n How many row to take for tabular printing 
    */ 
    def apply(df: org.apache.spark.sql.DataFrame, n: Int = 20, isHeaderNeeded: Boolean = true): Unit = 
    println(formatDf(df, n, isHeaderNeeded)) 

    def formatRows(rowSeparator: String, rows: Seq[String], isHeaderNeeded: Boolean): String = (
    rowSeparator :: 
    (rows.head + { if (isHeaderNeeded) "\n" + rowSeparator else "" }) :: 
    rows.tail.toList ::: 
    rowSeparator :: 
    List()).mkString("\n") 

    def formatRow(row: Seq[Any], colSizes: Seq[Int]) = { 
    val cells = (for ((item, size) <- row.zip(colSizes)) yield if (size == 0) "" else ("%" + size + "s").format(item)) 
    cells.mkString("|", "|", "|") 
    } 

    def rowSeparator(colSizes: Seq[Int]) = colSizes map { "-" * _ } mkString("+", "+", "+") 

}