多列不区分大小写的组
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多列不区分大小写的组相关的知识,希望对你有一定的参考价值。
反正有没有做LINQ2SQL查询做类似的事情:
var result = source.GroupBy(a => new { a.Column1, a.Column2 });
要么
var result = from s in source
group s by new { s.Column1, s.Column2 } into c
select new { Column1 = c.Key.Column1, Column2 = c.Key.Column2 };
但忽略了分组列内容的情况?
你可以将StringComparer.InvariantCultureIgnoreCase
传递给GroupBy
扩展方法。
var result = source.GroupBy(a => new { a.Column1, a.Column2 },
StringComparer.InvariantCultureIgnoreCase);
或者你可以根据ToUpperInvariant
的评论在每个领域使用Hamlet Hakobyan。我推荐ToUpperInvariant
或ToUpper
而不是ToLower
或ToLowerInvariant
,因为它针对程序化比较目的进行了优化。
我无法让NaveenBhat的解决方案工作,收到编译错误:
无法从用法中推断出方法'System.Linq.Enumerable.GroupBy(System.Collections.Generic.IEnumerable,System.Func,System.Collections.Generic.IEqualityComparer)'的类型参数。尝试显式指定类型参数。
为了使它工作,我发现最简单和最清楚的是定义一个新类来存储我的键列(GroupKey),然后是一个实现IEqualityComparer(KeyComparer)的单独类。然后我可以打电话
var result= source.GroupBy(r => new GroupKey(r), new KeyComparer());
KeyComparer类确实将字符串与InvariantCultureIgnoreCase比较器进行比较,因此感谢NaveenBhat将我指向正确的方向。
我的课程的简化版本:
private class GroupKey
{
public string Column1{ get; set; }
public string Column2{ get; set; }
public GroupKey(SourceObject r) {
this.Column1 = r.Column1;
this.Column2 = r.Column2;
}
}
private class KeyComparer: IEqualityComparer<GroupKey>
{
bool IEqualityComparer<GroupKey>.Equals(GroupKey x, GroupKey y)
{
if (!x.Column1.Equals(y.Column1,StringComparer.InvariantCultureIgnoreCase) return false;
if (!x.Column2.Equals(y.Column2,StringComparer.InvariantCultureIgnoreCase) return false;
return true;
//my actual code is more complex than this, more columns to compare
//and handles null strings, but you get the idea.
}
int IEqualityComparer<GroupKey>.GetHashCode(GroupKey obj)
{
return 0.GetHashCode() ; // forces calling Equals
//Note, it would be more efficient to do something like
//string hcode = Column1.ToLower() + Column2.ToLower();
//return hcode.GetHashCode();
//but my object is more complex than this simplified example
}
}
我通过Table中的DataRow对象的值进行了相同的问题分组,但我只是在DataRow对象上使用.ToString()来解决编译器问题,例如:
MyTable.AsEnumerable().GroupBy(
dataRow => dataRow["Value"].ToString(),
StringComparer.InvariantCultureIgnoreCase)
代替
MyTable.AsEnumerable().GroupBy(
dataRow => dataRow["Value"],
StringComparer.InvariantCultureIgnoreCase)
我已经扩展了Bill B的答案,让事情变得更有活力,以避免在GroupKey
和IQualityComparer<>
中“硬编码”列属性。
private class GroupKey
{
public List<string> Columns { get; } = new List<string>();
public GroupKey(params string[] columns)
{
foreach (var column in columns)
{
// Using 'ToUpperInvariant()' if user calls Distinct() after
// the grouping, matching strings with a different case will
// be dropped and not duplicated
Columns.Add(column.ToUpperInvariant());
}
}
}
private class KeyComparer : IEqualityComparer<GroupKey>
{
bool IEqualityComparer<GroupKey>.Equals(GroupKey x, GroupKey y)
{
for (var i = 0; i < x.Columns.Count; i++)
{
if (!x.Columns[i].Equals(y.Columns[i], StringComparison.OrdinalIgnoreCase)) return false;
}
return true;
}
int IEqualityComparer<GroupKey>.GetHashCode(GroupKey obj)
{
var hashcode = obj.Columns[0].GetHashCode();
for (var i = 1; i < obj.Columns.Count; i++)
{
var column = obj.Columns[i];
// *397 is normally generated by ReSharper to create more unique values
// So I added it here, it's technically not required
hashcode = (hashcode * 397) ^ (column != null ? column.GetHashCode() : 0);
}
return hashcode;
}
}
用法:
var result = source.GroupBy(r => new GroupKey(r.Column1, r.Column2, r.Column3), new KeyComparer());
这样,您可以将任意数量的列传递到GroupKey
构造函数中。
以上是关于多列不区分大小写的组的主要内容,如果未能解决你的问题,请参考以下文章