有几个类似的发声帖,但没有一个完全符合我的要求。
好的,想象一下,我有以下数据结构(简化了这个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"}},
};
对于属性&#34; Data&#34;,用户将告诉我GroupBy的哪些列序号;他们可能会说&#34;不要按任何事情进行分组,或者他们可能会说#34;按专栏分组[1]&#34;或者&#34;按列[0] 和列[1]和#34;分组。
如果我想按单列分组,我可以使用:
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 :(得分:2)
使用Row
数据结构,您要求的相对简单。
首先实施自定义IEqualityComparer<IEnumerable<string>>
:
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);
}
}
现在你可以有这样的方法:
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);
}
请注意,分组Key
类型为IEnumerable<string>
并包含columnIndexes
参数指定的选定行值,这就是我们需要自定义相等比较器的原因(否则它们将通过引用进行比较) ,这不会产生所需的行为。)
例如,要按列0和列2进行分组,您可以使用以下内容:
var result = GroupData(new [] { 0, 2 });
传递null
或空columnIndexes
将有效地产生单个群组,即无群组。
答案 1 :(得分:0)
你可以使用Recursive函数来创建动态lambdaExpression。但是你必须在函数中定义HardCode列。