2016-08-04 15 views
1

いくつかの同様のサウンドポストがありますが、まったく同じものはありません。Linqを使って動的にGroupByを作成する方法

わかりましたので、「データ」の特性のために私は(このLinqPad例のために簡略化)次のようなデータ構造

public class Row 
{ 
    public List<string> Columns { get; set; } 
} 

public List<Row> Data 
     => new List<Row> 
     { 
       new Row { Columns = new List<string>{ "A","C","Field3"}}, 
       new Row { Columns = new List<string>{ "A","D","Field3"}}, 
       new Row { Columns = new List<string>{ "A","C","Field3"}}, 
       new Row { Columns = new List<string>{ "B","D","Field3"}}, 
       new Row { Columns = new List<string>{ "B","C","Field3"}}, 
       new Row { Columns = new List<string>{ "B","D","Field3"}}, 
     }; 

を持っていることを想像し、ユーザーが列GROUPBYに序を私に教えてくれます。彼らは「何でもグループ化しない」と言うかもしれないし、「Column [1] by group [0] Column [1]」と言うかもしれない。

私は単一の列でグループ化したい場合は、私が使用することができます。

var groups = Data.GroupBy(d => d.Columns[i]); 
をそして、私は2列でグループ化したい場合は、私が使用することができます。

var groups = Data.GroupBy(d => new { A = d.Columns[i1], B = d.Columns[i2] }); 

しかし、数列の数は可変である(ゼロ - >多数)。データには数百の列が含まれ、ユーザーはGroupByに数十の列を追加することができます。

実行時に(動的に)このGroupByを作成するにはどうすればいいですか?

おかげ

グリフ

+0

何らかの形でラムダ式を作成することができます[動的OrderByについての非常によく似た質問に対するこの回答](http://stackoverflow.com/a/233505/424129)。 –

答えて

2

このデータ構造では、あなたは何を求めていますかは比較的簡単です。グループKeyタイプがIEnumerable<string>で、で指定された選択された行の値が含まれてい

public IEnumerable<IGrouping<IEnumerable<string>, Row>> GroupData(IEnumerable<int> columnIndexes = null) 
{ 
    if (columnIndexes == null) columnIndexes = Enumerable.Empty<int>(); 
    return Data.GroupBy(r => columnIndexes.Select(c => r.Columns[c]), ColumnEqualityComparer.Instance); 
} 

注:このようなメソッドを持つことができます

public class ColumnEqualityComparer : EqualityComparer<IEnumerable<string>> 
{ 
    public static readonly ColumnEqualityComparer Instance = new ColumnEqualityComparer(); 
    private ColumnEqualityComparer() { } 
    public override int GetHashCode(IEnumerable<string> obj) 
    { 
     if (obj == null) return 0; 
     // You can implement better hash function 
     int hashCode = 0; 
     foreach (var item in obj) 
      hashCode ^= item != null ? item.GetHashCode() : 0; 
     return hashCode; 
    } 
    public override bool Equals(IEnumerable<string> x, IEnumerable<string> y) 
    { 
     if (x == y) return true; 
     if (x == null || y == null) return false; 
     return x.SequenceEqual(y); 
    } 
} 

:カスタムIEqualityComparer<IEnumerable<string>>を実装することで

スタートcolumnIndexesパラメータであるため、カスタム同値比較器が必要でした(それ以外の場合は、参照によって比較され、必要な動作は生成されません)。 nullまたは空columnIndexesが効果的に単一のグループ、すなわちノーグループが生成されます渡す

var result = GroupData(new [] { 0, 2 }); 

:列0と2でグループにあなたがこのようなものを使用することができます。例えば

、。

0

ダイナミックlambdaExpressionを作成するためにあなたは再帰関数を使用することができます。関数内に列HardCodeを定義する必要があります。

関連する問題