【问题标题】:Select distinct only selects single column选择不同的只选择单列
【发布时间】:2012-11-15 02:59:52
【问题描述】:

基于这个问题:

[如何使用 LINQ 执行 SELECT UNIQUE?

我编写了以下表达式来从包含多个列的 dt 数据表中选择具有唯一 OrganizationID 列的行。

var distinctRows = (from DataRow dRow in dt.Rows
                    select new { col1 = dRow["OrganizationID_int"] }).Distinct();

但是当我在执行表达式后检查distinctRows 时,它只有一列(col1)的记录,而不是保存整个列。我担心添加 col2=... 等表达式可能会被解释为我想在所有这些列上选择不同的。

那么,如何在仅对 1 列而不是整列应用唯一过滤器时获取整行?

【问题讨论】:

  • 我不确定您要做什么。你能粘贴一些示例数据吗?
  • 如果多行具有相同的OrganizationID_int、第一、最后、最旧、最新、最高...,您要保留哪一行?
  • @Tim:我想要满足所有列的独特条件的整行。我想在下一步中迭代。
  • @Farshid:所以您只想要唯一的行并且不想按该字段分组,对吗?
  • @Farshid:添加了答案。 stackoverflow.com/a/13585738/284240

标签: c# linq distinct-values


【解决方案1】:

我想要满足该独特条件的所有行 列。我想在下一步中迭代。

因此,您不想按该字段分组并返回多行之一。您只需要唯一的行。

一种方法是使用Enumerable.GroupBy 并计算每个组中的行数:

var uniqueRows = dt.AsEnumerable()
                   .GroupBy(r => r.Field<int>("OrganizationID_int"))
                   .Where(g => g.Count() == 1)
                   .Select(g => g.First());

【讨论】:

  • g.First() 导致只有一行放置在 uniqueRows 中。你能建议我得到整行而不是第一行的方法吗?我需要在第二步中迭代 uniqueRows。
  • @Farshid:此代码将返回所有唯一行,而不仅仅是第一行。 GroupBy 可以返回多行,但由于我使用Where 来计算组,我确保只包含一行。这也意味着这个OrganizationID_int 在整个DataTable 中是独一无二的。但是,您需要 First,因为您希望得到 IEnumerable&lt;DataRow&gt; 作为结果。
【解决方案2】:

Distinct 异常方法有两种版本,其中一种采用IEqualityComparar,可以确定您将如何区分不同的元素。

这里是如何使用此方法的完整示例:

class Item
{
    public int Id {get; set;}
    public string Name {get;set;}
}

class ItemComparer : IEqualityComparer<Item>
{
    public bool Equals(Item x, Item y)
    {
        return x.Id == y.Id;
    }

    public int GetHashCode(Item x)
    {
        return x.Id;
    }
}

void Main()
{
  var sequence = new List<Item>() 
  {
      new Item {Id = 1, Name = "1"}, 
      new Item {Id = 1, Name = "2"}
  };

  // Using overloaded version of Distinct method!
  var distinctSequence = sequence.Distinct(new ItemComparer());

  // distinctSequence contains inly one Item with Id = 1
  distinctSequence.Dump();
}

【讨论】:

    【解决方案3】:

    您要查找的是GroupBy,然后是一个聚合函数,如MinSum 等,用于为每一列选择一个行值。

    var distinctRows = 
        (from DataRow dRow in dt.Rows
        group dRow by dRow["OrganizationID_int"] into g
        select new { OrgId = g.Key; Col2 = g.First().Col2, Col3 = g.First().Col3 })
    

    【讨论】:

    • 只能select g.First 而不是尝试在匿名对象中复制它。
    【解决方案4】:

    使用 Linq to DataSet 进行分组:

    var distinctRows = from row in dt.AsEnumerable()
                       group row by new { 
                          col1 = row.Field<int>("OrganizationID_int")
                          // other columns here 
                       } into g
                       select g.First();
    

    【讨论】:

    • 他想要唯一的行,所以 OrganizationID_int 的行是唯一的。
    • @Sergey:我不想一次排一排。我想要整行。
    • @Farshid 此查询返回所有不同的行(不是唯一的,而是不同的) - 返回具有唯一列值集的第一行。
    【解决方案5】:

    查看 MoreLinqDistinctBy method,您可以使用它来表达您的查询,如下所示:

    dt.Rows.DistinctBy(dRow => dRow["OrganizationID_int"])
    

    【讨论】:

      猜你喜欢
      • 2022-06-14
      • 2015-07-06
      • 1970-01-01
      • 1970-01-01
      • 2021-10-14
      • 2015-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多