. .
, NTuple. , Tuple <T> , Tuple < T1, T2 > , .., .NET. , NTuple . NTuple , , .
IEnumerable<string> columnsToGroupBy = ...;
NTuple :
var groups = dt.AsEnumerable()
.GroupBy(r => new NTuple<object>(from column in columnsToGroupBy select r[column]));
:
public class NTuple<T> : IEquatable<NTuple<T>>
{
public NTuple(IEnumerable<T> values)
{
Values = values.ToArray();
}
public readonly T[] Values;
public override bool Equals(object obj)
{
if (ReferenceEquals(this, obj))
return true;
if (obj == null)
return false;
return Equals(obj as NTuple<T>);
}
public bool Equals(NTuple<T> other)
{
if (ReferenceEquals(this, other))
return true;
if (other == null)
return false;
var length = Values.Length;
if (length != other.Values.Length)
return false;
for (var i = 0; i < length; ++i)
if (!Equals(Values[i], other.Values[i]))
return false;
return true;
}
public override int GetHashCode()
{
var hc = 17;
foreach (var value in Values)
hc = hc*37 + (!ReferenceEquals(value, null) ? value.GetHashCode() : 0);
return hc;
}
}
:
static void Main(string[] args)
{
var dt = new DataTable();
dt.Columns.Add("NAME", typeof(string));
dt.Columns.Add("CITY", typeof(string));
dt.Columns.Add("STATE", typeof(string));
dt.Columns.Add("VALUE", typeof(double));
dt.Rows.Add("Mike", "Tallahassee", "FL", 3);
dt.Rows.Add("Mike", "Tallahassee", "FL", 6);
dt.Rows.Add("Steve", "Tallahassee", "FL", 5);
dt.Rows.Add("Steve", "Tallahassee", "FL", 10);
dt.Rows.Add("Steve", "Orlando", "FL", 7);
dt.Rows.Add("Steve", "Orlando", "FL", 14);
dt.Rows.Add("Mike", "Orlando", "NY", 11);
dt.Rows.Add("Mike", "Orlando", "NY", 22);
IEnumerable<string> columnsToGroupBy = new[] {"CITY", "STATE"};
string columnToAggregate = "VALUE";
foreach (var group in dt.AsEnumerable().GroupBy(r => new NTuple<object>(from column in columnsToGroupBy select r[column])))
{
foreach (var keyValue in group.Key.Values)
{
Debug.Write(keyValue);
Debug.Write(':');
}
Debug.WriteLine(group.Sum(r => Convert.ToDouble(r[columnToAggregate])));
}
}