Beispiele:
var t = new Table<int>(new[] { new[] { 1, 2, 5 }, new[] { 5, 3, 5 } });
var t = new Table<int>(3, 3); // Tabellee ist 3x3 groß
t[0, 0] = 5; // 0|0 ist 5
oder
Table<int> t = "[1, 2, 5]\r[5, 3, 5]";
man kann auch einer spalte einen namen geben:
Table<int> t = "first [1, 2, 5]\rsecond [5, 3, 5]";
und so alle einträge in einer spalte bekommen oder setzen:
manuell einfach AddHeaders("first", "second");
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace fsm
{
[Serializable]
public class Table<T> : ICloneable, IEquatable<T[][]>, IEnumerable, IDisposable
{
private T[][] _data;
private List<string> Headers { get; set; }
public int ColumnCount { get; private set; }
public int RowCount { get; private set; }
public int Count => ColumnCount + RowCount;
public Table()
{
ColumnCount = 0;
RowCount = 0;
Headers = new List<string>();
}
public Table(int columnCount, int rowCount)
{
_data = new T[columnCount][];
ColumnCount = columnCount;
RowCount = rowCount;
Headers = new List<string>();
initData(rowCount);
}
public Table(T[][] src)
{
_data = src;
ColumnCount = src.Length;
RowCount = _data[0].Length;
Headers = new List<string>();
}
public void Expand(int columns, int rows)
{
for (int i = 0; i < columns; i++)
{
AddColumn();
}
for (int i = 0; i < rows; i++)
{
AddRow();
}
}
public void Expand()
{
Expand(1, 1);
}
public void AddColumn()
{
var tmp = new T[ColumnCount + 1][];
Array.Copy(_data, tmp, ColumnCount);
tmp[ColumnCount] = new T[RowCount];
_data = tmp;
ColumnCount++;
}
public void AddRow()
{
for (int i = 0; i < _data.Length; i++)
{
var l = new List<T>(_data[i]);
l.Add(default(T));
_data[i] = l.ToArray();
}
RowCount++;
}
public void AddHeader(string name)
{
Headers.Add(name);
}
public void AddHeaders(params string[] headers)
{
Headers.AddRange(headers);
}
public bool Contains(T value)
{
foreach (var item in _data)
{
foreach (var l in item)
{
if(l.Equals(value))
{
return true;
}
}
}
return false;
}
public bool ContainsColumn(T[] column)
{
foreach (var c in _data)
{
if(c == column)
{
return true;
}
}
return false;
}
public bool ContainsRow(T[] row)
{
foreach (var c in _data)
{
foreach (var r in c)
{
if(row.Equals(r))
{
return true;
}
}
}
return false;
}
public static Table<T> Parse(string src)
{
Table<T> ret = new Table<T>();
if(string.IsNullOrEmpty(src) || !src.Contains("[") || !src.Contains("]"))
{
throw new FormatException(nameof(src) + " has invalid format");
}
var s = src.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
T[][] result = new T[s.Length][];
int x = -1;
foreach (var line in s.Select(i => i.Trim()))
{
x++;
int headerIndex = line.IndexOf('[') - 1;
string l = null;
if (headerIndex > -1) {
var header = line.Substring(0, headerIndex);
l = line.Remove(0, header.Length + 1);
ret.AddHeader(header);
}
l = l.TrimStart('[').TrimEnd(']');
var r = new List<T>();
foreach (var item in l.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(i => i.Trim()))
{
r.Add((T)Convert.ChangeType(item, typeof(T)));
}
result[x] = r.ToArray();
}
ret._data = result;
return ret;
}
public static bool TryParse(string src, out Table<T> result)
{
Table<T> r;
try
{
r = Parse(src);
}
catch (Exception)
{
result = null;
return false;
}
result = r;
return true;
}
public void Clear()
{
_data = new T[ColumnCount][];
Headers = new List<string>();
initData(RowCount);
}
public void ClearAt(int x, int y)
{
this[x, y] = default(T);
}
public void ClearAllFrom(string header)
{
var hI = getHeaderIndex(header);
_data[hI] = new T[ColumnCount];
}
public T this[int x, int y]
{
get
{
if (x < 0 || y < 0) throw new IndexOutOfRangeException();
return _data[x][y];
}
set
{
_data[x][y] = value;
}
}
public T[] this[string header]
{
get
{
return _data[getHeaderIndex(header)];
}
set
{
_data[getHeaderIndex(header)] = value;
}
}
private void initData(int rowCount)
{
for (int c = 0; c < ColumnCount; c++)
{
for (int r = 0; r < rowCount; r++)
{
_data[c] = new T[ColumnCount];
}
}
}
private int getHeaderIndex(string header)
{
for (int i = 0; i < Headers.Count; i++)
{
if (Headers[i] == header)
{
return i;
}
}
throw new Exception("Header '" + header + "' not found");
}
private bool hasHeader(int index)
{
return index > -1 && index < Headers.Count;
}
#region "interface implementations"
public object Clone()
{
return MemberwiseClone();
}
public bool Equals(T[][] other)
{
return _data == other;
}
public IEnumerator GetEnumerator()
{
return _data.GetEnumerator();
}
public void Dispose()
{
_data = null;
GC.SuppressFinalize(this);
}
#endregion
public override string ToString()
{
var sb = new System.Text.StringBuilder();
for (int x = 0; x < ColumnCount; x++)
{
if(hasHeader(x))
{
sb.Append(Headers[x] + " ");
}
sb.Append("[");
for (int y = 0; y < RowCount; y++)
{
sb.Append(this[x, y] + ", ");
}
sb.Remove(sb.Length - 2, 2);
sb.Append("]" + '\r');
}
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
public override bool Equals(object obj)
{
return _data == ((Table<T>)obj)._data;
}
public override int GetHashCode()
{
return _data.GetHashCode();
}
#region "Operators"
public static implicit operator Table<T>(string s)
{
return Parse(s);
}
public static implicit operator string(Table<T> t)
{
return t.ToString();
}
#endregion
}
}
Kommentare zum Snippet