多列上不区分大小写的组

本文关键字:大小写 不区 | 更新日期: 2023-09-27 18:10:45

是否有这样做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);

或者您可以按照Hamlet Hakobyan在评论中建议的在每个字段上使用ToUpperInvariant。我推荐ToUpperInvariantToUpper而不是ToLowerToLowerInvariant,因为它针对编程比较目的进行了优化。

我无法得到NaveenBhat的解决方案工作,得到一个编译错误:

方法的类型参数"System.Linq.Enumerable.GroupBy (System.Collections.Generic.IEnumerable,系统。函数,system . collections . generic . eququalitycomparer)'不能从用法推断。尝试显式指定类型参数。

为了使它工作,我发现定义一个新类来存储我的键列(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
    }
}

我有同样的问题分组从表的DataRow对象的值,但我只是使用。tostring()上的DataRow对象来过去编译器的问题,例如

MyTable.AsEnumerable().GroupBy(
    dataRow => dataRow["Value"].ToString(),
    StringComparer.InvariantCultureIgnoreCase)

代替

MyTable.AsEnumerable().GroupBy(
    dataRow => dataRow["Value"],
    StringComparer.InvariantCultureIgnoreCase)

我对Bill B的回答进行了扩展,使事情变得更加动态,并避免在GroupKeyIQualityComparer<>中硬编码列属性。

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 hash values
            // So I added it here
            // (do keep in mind that multiplying each hash code by the same prime is more prone to hash collisions than using a different prime initially)
            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构造函数中。