【问题标题】:Keeping one row of nearly identical rows in a datatable using linq使用 linq 在数据表中保留一行几乎相同的行
【发布时间】:2018-10-05 18:36:25
【问题描述】:

我有一个数据表,其中可能存在几乎相同的行,除了一列“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 中使用它。这怎么可能?

【问题讨论】:

  • 添加选择子句?
  • Link 也许你在找什么。
  • FileID 添加到选择列列表中。

标签: c# linq datatable


【解决方案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();

【讨论】:

  • 非常感谢。这很好用。在没有CopyToDataTable 的情况下,我以不同的方式处理它,并且在它工作的同时添加了很多额外的代码。这样干净多了。
  • 刚刚也看到了更新。每个组最多只有少数重复行,所以我认为它不会有太大变化,但我会尝试 MaxBy 看看它的比较情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
相关资源
最近更新 更多