在IEnumerable<DataRow>上进行分组

3

我有一组 DataRow 对象。基于列 'URL_Link',我应该选择不同的行。参考这篇帖子,我想到了下面的代码。
是否可以将其应用于 DataRow 集合?

IEnumerable<DataRow> results = GetData();  
results.GroupBy(row => row.Field<string>("URL_Link")).Select(grp => grp.First());

这段代码语法正确,但是它并没有解决问题。它不能移除重复的行。我错在哪里了?

2个回答

5
除了你没有将结果集重新分配给result变量的小错误之外。
个人认为,如果您确实应该接收不同的值,则使用distinct要清晰得多。在这种情况下,使用groupby并不是很清晰。如果打算返回整行,请参阅下面的第一个示例或其他第二个示例。
    class Program
    {
        static DataTable GetData()
        {
            DataTable table = new DataTable();
            table.Columns.Add("Visits", typeof(int));
            table.Columns.Add("URL_Link", typeof(string));

            table.Rows.Add(57, "yahoo.com");
            table.Rows.Add(130, "google.com");
            table.Rows.Add(92, "google.com");
            table.Rows.Add(25, "home.live.com");
            table.Rows.Add(30, "stackoverflow.com");
            table.Rows.Add(1, "stackoverflow.com");
            table.Rows.Add(7, "mysite.org");
            return table;
    }

    static void Main(string[] args)
    {
        var res = GetData()
                  .AsEnumerable()
                  .GroupBy(row => row.Field<string>("URL_Link"))
                  .Select(grp => grp.First());

        foreach (var item in res)
        {
            string text = "";
            foreach (var clm in item.ItemArray)
                text += string.Format("{0}\t", clm);

            Console.WriteLine(text);
        }
        Console.ReadLine();
    }
}

这与您已经提供的大致相同。首先,您没有重新分配变量。然后,您应该从ItemArray中访问字段。您可以参考上面的示例,它给出了以下输出:
57    yahoo.com
130   google.com
25    home.live.com
30    stackoverflow.com
7     mysite.com

请记住,根据您需要返回这些行中的特定内容(例如最多访问的重复内容),您可能需要指定Select、Orderby和Where子句。
如果您只需要或想要从不同的结果中返回URL_Link字段,则此示例非常清晰和简单。它只需要选择您想要的字段,然后对其进行去重。
    static void Main(string[] args)
    {
        var res = GetData()
                    .AsEnumerable()
                    .Select(d=>d.Field<string>("URL_Link"))
                    .Distinct();

        foreach (var item in res)
            Console.WriteLine(item.ToString());  

        Console.ReadLine();
    }

“Distinct()” 也是我的最初想法,但它只返回不同的值(列),而不是行,是吗? - abatishchev
1
Distinct()使用IEqualityComparer<T>接口来确定哪些项目是相似的。您可以创建自己的实现,并将其提供给“Distinct()`调用。这样,您就可以在完整数据集上调用Distinct()并通过仅比较“URL_Link”来获取完整行。 - Raxr
@abatishchev 好的,没错。他走在正确的轨道上。我会编辑回复。 - Independent

3

您的LINQ操作返回的结果并没有被赋值给任何变量:

IEnumerable<DataRow> results = GetData();  
results = results.GroupBy(row => row.Field<string>("URL_Link")).Select(grp => grp.First());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接