如何使用Linq
本文关键字:Linq 何使用 | 更新日期: 2023-09-27 18:00:58
有几个听起来类似的帖子,但没有一个完全符合我的要求。
好吧,假设我有以下数据结构(对于这个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"}},
};
对于属性"Data",用户会告诉我要GroupBy的列序号;他们可以说"不要按任何东西分组",也可以说"按列[1]分组"或"按列[0]分组和列[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?
感谢
Griff
有了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
将有效地产生单个组,即不分组。
您可以使用递归函数来创建动态lambdaExpression。但是必须在函数中定义列HardCode。