仅基于表的一个字段在Linq中不同


133

我试图在Linq中使用.distinct来基于表的一个字段获取结果(因此不需要从表中复制整个记录)。

我知道写使用如下的基本查询:

var query = (from r in table1
orderby r.Text
select r).distinct();

但我需要r.text没有重复的结果。


您需要指定要区分的字段,请参阅msdn.microsoft.com/en-us/library/bb348436.aspx
Antarr Byrd 2013年

Answers:


300

试试这个:

table1.GroupBy(x => x.Text).Select(x => x.FirstOrDefault());

这将对表进行分组,Text并使用每个组中的第一行,从而得到Text不同的行。


2
如果groupby有多个字段怎么办?

6
@ user585440:在这种情况下,您将使用匿名类型,例如:table1.GroupBy(x => new { x.Text, x.Property2, x.Property3 }).Select(x => x.First());
Daniel Hilgarth

2
是的,您说得对,我已经找到了。不管怎么说,还是要谢谢你。而且我还发现Select(x => x.First())可能导致崩溃。最好更改为Select(x => x.FirstOrDefault());

6
我必须使用FirstOrDefault,否则会发生运行时错误
TruthOf42 '16

2
@ TruthOf42这不太可能。GroupBy不会创建空组,请参阅我之前的评论。您的代码很可能包含的内容超出了您在此处看到的内容。也许你有一个Where良好的条件First
Daniel Hilgarth '16

26

MoreLinq具有可使用的DistinctBy方法:

它将允许您执行以下操作:

var results = table1.DistictBy(row => row.Text);

该方法的实现(缺少参数验证)如下:

private static IEnumerable<TSource> DistinctByImpl<TSource, TKey>(IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
    HashSet<TKey> knownKeys = new HashSet<TKey>(comparer);
    foreach (TSource element in source)
    {
        if (knownKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}

抱歉,我不热衷于使用equityComparer。
Megha Jain

@MeghaJain好吧,无论如何,都会使用GroupBy一个,也需要一个。EqualityComparer如果未提供,则这两种方法都将使用默认值。
2013年

9
好吧,如果我错了,请纠正我,但是这里的区别是在内存中完成的,而不是在DB中完成的?这会导致不希望的全扫描吗?
Kek 2013年

@Kek。不,由于收益率高,您将在第一个不同元素处停止。最终,是的,您将每个密钥加载到HashSet中,但是由于它是IEnumerable in和IEnumerable out,因此您只会得到这些项。如果您正在谈论LINQ to SQL,那么可以,这将进行表扫描。
PRMan

12

但是我需要不重复r.text的结果

听起来好像您想要这样:

table1.GroupBy(x => x.Text)
      .Where(g => g.Count() == 1)
      .Select(g => g.First());

这将选择Text唯一的行。



3

关于此主题有很多讨论。

您可以在这里找到其中之一:

最受欢迎的建议之一是像@Servy所指出的以lambda表达式为参数的Distinct方法。

C#的首席架构师Anders Hejlsberg在这里提出了解决方案。还说明了框架设计团队为何决定不添加重载Lambda的Distinct方法。


2

根据我的发现,您的查询基本上是正确的。只需将“ select r”更改为“ select r.Text”就可以解决问题。这就是MSDN如何记录其应如何工作的方式。

例如:

    var query = (from r in table1 orderby r.Text select r.Text).distinct();

您更改了这种情况下可能不需要的“选择”语句
faza

1
data.Select(x=>x.Name).Distinct().Select(x => new SelectListItem { Text = x });


-5

您可以尝试以下方法:table1.GroupBy(t => t.Text).Select(shape => shape.r)).Distinct();

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.