using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace datatable
{
public class ConsoleTable
{
/// <summary>
/// This will hold the header of the table.
/// </summary>
private string[] header; /// <summary>
/// This will hold the rows (lines) in the table, not including the
/// header. I'm using a List of lists because it's easier to deal with...
/// </summary>
private List<List<string>> rows; /// <summary>
/// This is the default element (character/string) that will be put
/// in the table when user adds invalid data, example:
/// ConsoleTable ct = new ConsoleTable();
/// ct.AddRow(new List<string> { null, "bla", "bla" });
/// That null will be replaced with "DefaultElement", also, empty
/// strings will be replaced with this value.
/// </summary>
private const string DefaultElement = "X"; public enum AlignText
{
ALIGN_RIGHT,
ALIGN_LEFT,
} public ConsoleTable()
{
header = null;
rows = new List<List<string>>();
TextAlignment = AlignText.ALIGN_LEFT;
} /// <summary>
/// Set text alignment in table cells, either RIGHT or LEFT.
/// </summary>
public AlignText TextAlignment
{
get;
set;
} public void SetHeaders(string[] h)
{
header = h;
} public void AddRow(List<string> row)
{
rows.Add(row);
} private void AppendLine(StringBuilder hsb, int length)
{
// " " length is 1
// "\r\n" length is 2
// +1 length because I want the output to be prettier
// Hence the length - 4 ...
hsb.Append(" ");
hsb.Append(new string('-', length - ));
hsb.Append("\r\n");
} /// <summary>
/// This function returns the maximum possible length of an
/// individual row (line). Of course that if we use table header,
/// the maximum length of an individual row should equal the
/// length of the header.
/// </summary>
private int GetMaxRowLength()
{
if (header != null)
return header.Length;
else
{
int maxlen = rows[].Count;
for (int i = ; i < rows.Count; i++)
if (rows[i].Count > maxlen)
maxlen = rows[i].Count; return maxlen;
}
} private void PutDefaultElementAndRemoveExtra()
{
int maxlen = GetMaxRowLength(); for (int i = ; i < rows.Count; i++)
{
// If we find a line that is smaller than the biggest line,
// we'll add DefaultElement at the end of that line. In the end
// the line will be as big as the biggest line.
if (rows[i].Count < maxlen)
{
int loops = maxlen - rows[i].Count;
for (int k = ; k < loops; k++)
rows[i].Add(DefaultElement);
}
else if (rows[i].Count > maxlen)
{
// This will apply only when header != null, and we try to
// add a line bigger than the header line. Remove the elements
// of the line, from right to left, until the line is equal
// with the header line.
rows[i].RemoveRange(maxlen, rows[i].Count - maxlen);
} // Find bad data, loop through all table elements.
for (int j = ; j < rows[i].Count; j++)
{
if (rows[i][j] == null)
rows[i][j] = DefaultElement;
else if (rows[i][j] == "")
rows[i][j] = DefaultElement;
}
}
} /// <summary>
/// This function will return an array of integers, an element at
/// position 'i' will return the maximum length from column 'i'
/// of the table (if we look at the table as a matrix).
/// </summary>
private int[] GetWidths()
{
int[] widths = null;
if (header != null)
{
// Initially we assume that the maximum length from column 'i'
// is exactly the length of the header from column 'i'.
widths = new int[header.Length];
for (int i = ; i < header.Length; i++)
widths[i] = header[i].ToString().Length;
}
else
{
int count = GetMaxRowLength();
widths = new int[count];
for (int i = ; i < count; i++)
widths[i] = -;
} foreach (List<string> s in rows)
{
for (int i = ; i < s.Count; i++)
{
s[i] = s[i].Trim();
if (s[i].Length > widths[i])
widths[i] = s[i].Length;
}
} return widths;
} /// <summary>
/// Returns a valid format that is to be passed to AppendFormat
/// member function of StringBuilder.
/// General form: "|{i, +/-widths[i]}|", where 0 <= i <= widths.Length - 1
/// and widths[i] represents the maximum width from column 'i'.
/// </summary>
/// <param name="widths">The array of widths presented above.</param>
private string BuildRowFormat(int[] widths)
{
string rowFormat = String.Empty;
for (int i = ; i < widths.Length; i++)
{
if (TextAlignment == AlignText.ALIGN_LEFT)
rowFormat += "| {" + i.ToString() + ",-" + (widths[i]) + "} ";
else
rowFormat += "| {" + i.ToString() + "," + (widths[i]) + "} ";
} rowFormat = rowFormat.Insert(rowFormat.Length, "|\r\n");
return rowFormat;
} /// <summary>
/// Prints the table, main function.
/// </summary>
public void PrintTable()
{
if (rows.Count == )
{
Console.WriteLine("Can't create a table without any rows.");
return;
}
PutDefaultElementAndRemoveExtra(); int[] widths = GetWidths();
string rowFormat = BuildRowFormat(widths); // I'm using a temporary string builder to find the total width
// of the table, and increase BufferWidth of Console if necessary.
StringBuilder toFindLen = new StringBuilder();
toFindLen.AppendFormat(rowFormat, (header == null ? rows[].ToArray() : header));
int length = toFindLen.Length;
if (Console.BufferWidth < length)
Console.BufferWidth = length; // Print the first row, or header (if it exist), you can see that AppendLine
// is called before/after every AppendFormat.
StringBuilder hsb = new StringBuilder();
AppendLine(hsb, length);
hsb.AppendFormat(rowFormat, (header == null ? rows[].ToArray() : header));
AppendLine(hsb, length); // If header does't exist, we start from 1 because the first row
// was already printed above.
int idx = ;
if (header == null)
idx = ;
for (int i = idx; i < rows.Count; i++)
{
hsb.AppendFormat(rowFormat, rows[i].ToArray());
AppendLine(hsb, length);
} Console.WriteLine(hsb.ToString());
} static void Main(string[] args)
{
// Some test table, with header, and 3 lines by 3 columns.
ConsoleTable ct = new ConsoleTable();
ct.TextAlignment = ConsoleTable.AlignText.ALIGN_RIGHT;
ct.SetHeaders(new string[] { "ID", "Name", "City" });
ct.AddRow(new List<string> { "", "John", "New York" });
ct.AddRow(new List<string> { "", "Mark", "Washington" });
ct.AddRow(new List<string> { "", "Alice", "Chicago" });
ct.PrintTable();
}
}
}

C# Tips: Draw a data table in console的更多相关文章

  1. [Javascript] Logging Pretty-Printing Tabular Data to the Console

    Learn how to use console.table to render arrays and objects in a tabular format for easy scanning ov ...

  2. data.table包

    data.table 1.生成一个data.table对象 生成一个data.table对象,记为DT. library(data.table) :],V3=round(rnorm(),),V4=:) ...

  3. R之data.table -melt/dcast(数据合并和拆分)

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 30.0px "Helvetica Neue"; color: #323333 } p. ...

  4. R之data.table速查手册

    R语言data.table速查手册 介绍 R中的data.table包提供了一个data.frame的高级版本,让你的程序做数据整型的运算速度大大的增加.data.table已经在金融,基因工程学等领 ...

  5. 两种Data Table参数化设置的区别

    首先介绍Data Table的语法: 1.DataTable.value(ParameterID, SheetID) 2.DataTable(ParameterID, SheetID) 以上2种方法的 ...

  6. R语言数据分析利器data.table包 —— 数据框结构处理精讲

        R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代码简洁,只要一行命令就可以完成诸多任务,另一方面是处理 ...

  7. R语言基因组数据分析可能会用到的data.table函数整理

    R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代码简洁,只要一行命令就可以完成诸多任务,另一方面是处理快,内部 ...

  8. 将基因组数据分类并写出文件,python,awk,R data.table速度PK

    由于基因组数据过大,想进一步用R语言处理担心系统内存不够,因此想着将文件按染色体拆分,发现python,awk,R 语言都能够非常简单快捷的实现,那么速度是否有差距呢,因此在跑几个50G的大文件之前, ...

  9. data.table包简介

    data.table包主要特色是:设置keys.快速分组和滚得时序的快速合并.data.table主要通过二元检索法大大提高数据操作的效率,同时它也兼容适用于data.frame的向量检索法. req ...

随机推荐

  1. maven的学习系列(四)—创建maven项目注意事项

    文件夹: <1> 中央工厂的位置 <2>mvn archetype:generate <3>Eclipse配置maven <4>在Eclipse中创建简 ...

  2. VS2013 安装phonegap

    https://www.microsoft.com/en-us/download/details.aspx?id=40783

  3. 标准SAP中的物料类型

    DIEN -服务 ERSA -备件 FERT -成品 HALB -半成品 HAWA -贸易商品 HIBE -经营供应 LEER -虚拟件 NLAG -费存储物料 ROH -原材料 VERP -包装 W ...

  4. UVALive 4223 Trucking 二分+spfa

    Trucking 题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8& ...

  5. HDU 5573 Binary Tree 构造

    Binary Tree 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5573 Description The Old Frog King lives ...

  6. C#实现一个最简单的HTTP服务器

    简介 本文用C#实现了一个最简单的HTTP服务器类,你可以将它嵌入到自己的项目中,或者也可以阅读代码来学习关于HTTP协议的知识. 背景 高性能的WEB应用一般都架设在强大的WEB服务器上,例如IIS ...

  7. C#的WinForm中制作饼状图和柱状图

    using System; using System.IO;//用于文件存取 using System.Data;//用于数据访问 using System.Drawing;//提供画GDI+图形的基 ...

  8. Android游戏开发:物理游戏之重力系统开发--圆形自由落体Demo

    本节为大家提供有关物理游戏的知识,讲解了一个简单的圆形自由落体Demo的编写.. Java代码 package com.himi; import java.util.Random; import ja ...

  9. linux下网络编程常见问题

    网络程序异常退出无core文件产生 这种情况发生在一边连接端已经关闭,但是另外一边还在对连接句柄做send操作,这样做send操作的进程会收到SIGPIPE信号,默认行为是直接退出且不会产生core. ...

  10. SVM多分类

    http://www.matlabsky.com/thread-9471-1-1.htmlSVM算法最初是为二值分类问题设计的,当处理多类问题时,就需要构造合适的多类分类器.目前,构造SVM多类分类器 ...