2016-09-07 36 views
0

当我在下图中应用DISTINCT.ToList()时,将从结果列表中删除哪些项目? 是否将第一个条目(即第一个添加到列表中)重复保存在要返回的新列表中?如果没有,是否有办法让DISTINCT.ToList()保留新列表中的重复项中的第一个条目被返回?在使用List.Distinct()时返回项目在结果列表中的顺序

Dim values As List(Of Integer) = New List(Of Integer) 
    values.Add(1) 
    values.Add(5) 
    values.Add(2) 
    values.Add(3) 
    values.Add(2) 
    values.Add(3) 
    values.Add(4) 
    values.Add(2) 
    values.Add(2) 
    values.Add(3) 
    values.Add(3) 
    values.Add(3) 

    Dim items As List(Of Integer) = values.Distinct().ToList 

    ' Display result. 
    For Each i As Integer In items 
     Console.WriteLine(i) 
    Next 

Expected output: 
1 
5 
2 
3 
4 

MSDN页面上显示 “鲜明(中TSource)(IEnumerable的(中TSource))方法返回一个不包含重复值无序序列”。有没有办法解决这个问题?

+2

实际上,没有项目将从列表中删除,包含不同项目的新列表将被返回。 – hellowstone

+1

您可以随时添加一个扩展方法,你自己,做为了它:'公共静态IOrderedEnumerable OrderedDistinct(这IEnumerable的数据){返回data.Distinct()排序依据(X => X)。 }' – Maarten

+0

用'Distinct'操作返回的列表仅包含第一个发生的原始项目,并且没有排序。所以你必须期望在你的例子中你的预期输出。 – hellowstone

回答

4

不,你不能使用Distinct来解决这个问题。正如它所发生的那样,它的工作原理与您的预期完全相同,但文档明确指出它不能保证。因此,在未来的框架版本中实现可能会发生变化,因此您不能依赖它。该方法编写简单。事实上,你甚至可以复制the framework implementation

再次 - 它目前的工作方式如你所愿,但不保证将来会这样做。

另一方面,我非常有信心这个实现永远不会改变,因为我无法想象更高效的实现存在。

下面是完整的实现(抱歉,这是C#和VB.NET不)

public static class MyEnumerable 
{ 
    public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source) 
    { 
     if (source == null) 
     { 
      throw new ArgumentNullException(nameof(source)); 
     } 

     var items = new HashSet<T>(); 

     foreach (T item in source) 
     { 
      if (items.Add(item)) 
      { 
       yield return item; 
      } 
     } 
    } 
} 
1

不,你不能左右它获得与该框架提供的标准方法。你可以像Stilgar建议的那样自己编写代码来绕过它。

随着提供的指数选择的第一个项目的例子在技术上是不相关的,你将无法知道,如果它是第一个或第100出现在自诠释名单是结构。

但这说我猜你正在使用自定义对象。在这种情况下,您的订单来自某种排序。在这种情况下,我建议你,而不是你的OrderBy<>语句中使用GroupBy<>,然后为每个组订单中的项目,并做一个First<>

Group by和Distinct非常接近。不同的可以被一个组取代,然后每个组首先取代。事实上,它比真正的实现要慢得多,但是这里的目标是解释如果你最终需要的不仅仅是第一项,你如何使用它来定制输出。

相关问题