【问题标题】:Remove duplicate rows of a datatable based on a list of key fields根据关键字段列表删除数据表的重复行
【发布时间】:2015-08-13 16:17:29
【问题描述】:

我正在使用以下代码根据一个字段的值 (keyField) 删除 DataTable 中的重复行

IEnumerable<DataRow> uniqueContacts = dt.AsEnumerable()
                    .GroupBy(x =>  x[keyField].ToString())
                    .Select(g => g.First());
DataTable dtOut = uniqueContacts.CopyToDataTable();

如何升级此代码,以便我的 LINQ 根据字段列表的值删除重复项。例如删除所有具有相同 'firstname' 和 'lastname' 的行?

【问题讨论】:

    标签: c# linq datatable


    【解决方案1】:

    你可以使用匿名类型:

    IEnumerable<DataRow> uniqueContacts = dt.AsEnumerable()
                        .GroupBy(row =>  new { 
                            FirstName = row.Field<string>("FirstName"),
                            LastName  = row.Field<string>("LastName")
                        })
                        .Select(g => g.First());
    

    由于您想要一个与编译时未知的List&lt;string&gt; 一起使用的解决方案,您可以使用此类:

    public class MultiFieldComparer : IEquatable<IEnumerable<object>>, IEqualityComparer<IEnumerable<object>>
    {
        private IEnumerable<object> objects;
    
        public MultiFieldComparer(IEnumerable<object> objects)
        {
            this.objects = objects;
        }
    
        public bool Equals(IEnumerable<object> x, IEnumerable<object> y)
        {
            return x.SequenceEqual(y);
        }
    
        public int GetHashCode(IEnumerable<object> objects)
        {
            unchecked
            {
                int hash = 17;
                foreach (object obj in objects)
                    hash = hash * 23 + (obj == null ? 0 : obj.GetHashCode());
                return hash;
            }
        }
    
        public override int GetHashCode()
        {
            return GetHashCode(this.objects);
        }
    
        public override bool Equals(object obj)
        {
            MultiFieldComparer other = obj as MultiFieldComparer;
            if (other == null) return false;
            return this.Equals(this.objects, other.objects);
        }
    
        public bool Equals(IEnumerable<object> other)
        {
            return this.Equals(this.objects, other);
        }
    }
    

    还有这个使用这个类的扩展方法:

    public static IEnumerable<DataRow> RemoveDuplicates(this IEnumerable<DataRow> rows, IEnumerable<string> fields)
    {
        return rows
            .GroupBy(row => new MultiFieldComparer(fields.Select(f => row[f])))
            .Select(g => g.First());
    }
    

    那么就很简单了:

    List<string> columns = new List<string> { "FirstName", "LastName" };
    var uniqueContacts = dt.AsEnumerable().RemoveDuplicates(columns).CopyToDataTable();
    

    【讨论】:

    • 它应该适用于关键字段列表,而不仅仅是FirstNameLastName。我只是举个例子。
    • @Pedram:我也给了你一个例子。用更多字段扩展它有什么问题?
    • 关键字段列表是函数的输入。所以我们不知道他们会提前叫什么。
    • @Pedram:我提供了一种动态方法。
    • 哦,太好了!让我试一试,然后回来找你。
    猜你喜欢
    • 2011-04-21
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    相关资源
    最近更新 更多