使用linq在数据表中保留一行几乎相同的行

时间:2018-10-05 18:36:26

标签: c# linq datatable

我有一个数据表,其中可能存在几乎相同的行,但一列“ FileID”中的值除外。可以不同的列包含Int32数据,当行重复时,我只想保留具有该列最大值的行。如果行不是重复的,我想保留单行。

var Test = dt.AsEnumerable()
                .GroupBy(r => new
                {
                    Tool = r.Field<string>("Tool"),
                    Plate = r.Field<string>("Plate"),
                    Lot = r.Field<string>("Lot"),
                    Time1 = r.Field<DateTime>("Time1"),
                    Tool2 = r.Field<string>("Tool2"),
                    Time2 = r.Field<DateTime>("Time2"),
                    Recipe = r.Field<string>("Recipe"),
                    Row = r.Field<Int16>("Row")
                }).OrderBy(t => t.Max(r => r.Field<Int32>("FileID")));

这似乎正确地过滤了行,但是我丢失了FileID列。我想将此查询的结果放回具有最大FileID的数据表中,以便可以在表单的datagridview中使用它。这怎么可能?

1 个答案:

答案 0 :(得分:1)

按适当的列分组后,您只需从每个组中选择最大为FileID的行,然后即可使用CopyToDataTable扩展名:

var ans = dt.AsEnumerable()
            .GroupBy(r => new {
                Tool = r.Field<string>("Tool"),
                Plate = r.Field<string>("Plate"),
                Lot = r.Field<string>("Lot"),
                Time1 = r.Field<DateTime>("Time1"),
                Tool2 = r.Field<string>("Tool2"),
                Time2 = r.Field<DateTime>("Time2"),
                Recipe = r.Field<string>("Recipe"),
                Row = r.Field<Int16>("Row")
            })
            .Select(rg => rg.OrderByDescending(r => r.Field<Int32>("FileID")).First())
            .CopyToDataTable();

注意:假设您使用的是LINQ to Objects,OrderBy / First并不是查找具有最大FileID的行的最有效方法。您可能没有足够的数据要紧,但是可以使用扩展方法MaxBy,该方法对数据进行一次遍历并找到适当的行:

public static T MaxBy<T, TKey>(this IEnumerable<T> src, Func<T, TKey> keySelector) => src.Aggregate((a, b) => Comparer<TKey>.Default.Compare(keySelector(a), keySelector(b)) > 0 ? a : b);

var ans = dt.AsEnumerable()
            .GroupBy(r => new {
                Tool = r.Field<string>("Tool"),
                Plate = r.Field<string>("Plate"),
                Lot = r.Field<string>("Lot"),
                Time1 = r.Field<DateTime>("Time1"),
                Tool2 = r.Field<string>("Tool2"),
                Time2 = r.Field<DateTime>("Time2"),
                Recipe = r.Field<string>("Recipe"),
                Row = r.Field<Int16>("Row")
            })
            .Select(rg => rg.MaxBy(r => r.Field<Int32>("FileID")))
            .CopyToDataTable();