2011-09-24 55 views
11

Tôi cần hiển thị bảng trong bảng điều khiển.Scala: Vẽ bảng thành bàn điều khiển

giải pháp đơn giản của tôi, nếu bạn muốn gọi nó là một "giải pháp", là như sau:

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 

    } 

Chúng tôi không phải tranh luận này

  • một là tìm cách xấu khi hiển thị
  • mã b trông có vẻ lộn xộn

Thực ra, một câu hỏi như vậy đã được yêu cầu C# nhưng tôi muốn để biết một giải pháp tốt cho Scala.

Vì vậy, một cách (tốt/tốt/đơn giản/bất kỳ) là gì để vẽ một bảng như vậy trong Scala sang bàn điều khiển?

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

Trả lời

24

Tôi đã kéo sau từ dự án hiện tại của tôi:

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

điều này thật đẹp. Đã thử nó và chính xác là những gì tôi đang tìm kiếm. – evildead

+4

như là một bổ sung này là trái alignement ("%" + size + "s") định dạng (mục) quyền này ("% -" + size + "s"). Định dạng (mục) – evildead

+1

Sẽ đẹp hơn như là một 'lớp ngầm định' bổ sung ví dụ '.asTable', ví dụ: 'Seq [Seq [Any]]' :) –

2

Tokenize. Tôi muốn bắt đầu với nhìn vào thực hiện một vài đối tượng vụ án và các lớp học để bạn tạo ra một danh sách tokenized có thể hoạt động trên cho mục đích hiển thị:

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 
} 

Vì vậy, sau đó bạn có thể hình thành trở ngại nhất định với một số loại đối tượng liên tiếp :

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

Sau đó, bạn có thể kiểm tra các ràng buộc và những thứ tương tự trong thời trang không thể thay đổi. Có thể tạo các phương thức để thêm các bảng và căn chỉnh ...

case class Table(contents: List[TableTokens]) 

Điều đó có nghĩa là bạn có thể có một vài biến thể khác nhau về phong cách khác với cấu trúc của bạn, la HTML và CSS.

+0

có thể bạn có thể thêm một ví dụ nhỏ. Tôi không nhận được nó đầy đủ. – evildead

+0

Tôi thứ hai @ evildead-tại sao tokenize bất cứ điều gì nếu điều này là về rendering một chuỗi hiện có? –

2

Tôn cảm ơn cho mã bộ phận của máy đánh chữ!

Có một sửa đổi cho Spark in bảng dữ liệu.

tôi có nghĩa là bạn có thể in nội dung DataFrame hoặc kéo tập hợp kết quả, như

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

thứ hai sẽ không có tiêu đề tất nhiên, để thực hiện DF bạn có thể đặt bao nhiêu hàng để kéo từ khung dữ liệu Spark cho in ấn và bạn cần tiêu đề hay không.

/** 
* 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("+", "+", "+") 

} 
Các vấn đề liên quan