C# 使用List.Distinct()时返回结果列表中项目的顺序

C# 使用List.Distinct()时返回结果列表中项目的顺序,c#,vb.net,list,ienumerable,C#,Vb.net,List,Ienumerable,在下图中应用DISTINCT.ToList()时,将从结果列表中删除哪些项目? 副本中的第一个条目(即第一次添加到列表中的条目)是否保留在返回的新列表中?如果没有,是否有方法使与众不同。ToList()保留要返回的新列表中重复项中的第一个条目 Dim values As List(Of Integer) = New List(Of Integer) values.Add(1) values.Add(5) values.Add(2) values.Add(3

在下图中应用
DISTINCT.ToList()
时,将从结果列表中删除哪些项目? 副本中的第一个条目(即第一次添加到列表中的条目)是否保留在返回的新列表中?如果没有,是否有方法使
与众不同。ToList()
保留要返回的新列表中重复项中的第一个条目

    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

此页面显示“Distinct(Of TSource)(IEnumerable(Of TSource))方法返回一个无序序列,其中不包含重复值”。有办法解决这个问题吗?

不,您不能使用Distinct来解决这个问题。碰巧,它的工作原理与您期望的完全一样,但文档中明确指出,它不能得到保证。因此,该实现可以在框架的未来版本中更改,因此您不能依赖它。这个方法写起来很简单。事实上,你甚至可以复制

同样,它目前可以按照您的要求工作,但不能保证将来会这样做

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

这是一个完整的实现(抱歉,它是C#而不是VB.NET)

公共静态类MyEnumerable
{
公共静态IEnumerable Distinct(此IEnumerable源)
{
if(source==null)
{
抛出新ArgumentNullException(nameof(source));
}
var items=newhashset();
foreach(源中的T项)
{
如果(项目。添加(项目))
{
收益回报项目;
}
}
}
}

不,您不能使用Distinct来解决这个问题。碰巧,它的工作原理与您期望的完全一样,但文档中明确指出,它不能得到保证。因此,该实现可以在框架的未来版本中更改,因此您不能依赖它。这个方法写起来很简单。事实上,你甚至可以复制

同样,它目前可以按照您的要求工作,但不能保证将来会这样做

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

这是一个完整的实现(抱歉,它是C#而不是VB.NET)

公共静态类MyEnumerable
{
公共静态IEnumerable Distinct(此IEnumerable源)
{
if(source==null)
{
抛出新ArgumentNullException(nameof(source));
}
var items=newhashset();
foreach(源中的T项)
{
如果(项目。添加(项目))
{
收益回报项目;
}
}
}
}

不,你不能用框架提供的标准方法来解决这个问题。你可以像斯蒂尔加建议的那样自己编写代码来绕过它

在您提供的示例中,按索引选择第一项在技术上是不相关的,因为您无法知道这是列表中的第一次还是第100次出现,因为Int是结构

但我猜您使用的是自定义对象。在这种情况下,您的订单来自某种排序。在这种情况下,我建议您改为使用
GroupBy
,然后根据您的
OrderBy
语句为每个组订购项目,并首先对其执行
操作


“分组方式”和“不同方式”非常接近。distinct可以由一个组替换,然后在每个组上先替换。事实上,它比实际实现慢得多,但这里的目标是解释如果最终需要的不仅仅是第一项,如何使用它来定制输出。

不,您无法使用框架提供的标准方法来解决它。你可以像斯蒂尔加建议的那样自己编写代码来绕过它

在您提供的示例中,按索引选择第一项在技术上是不相关的,因为您无法知道这是列表中的第一次还是第100次出现,因为Int是结构

但我猜您使用的是自定义对象。在这种情况下,您的订单来自某种排序。在这种情况下,我建议您改为使用
GroupBy
,然后根据您的
OrderBy
语句为每个组订购项目,并首先对其执行
操作


“分组方式”和“不同方式”非常接近。distinct可以由一个组替换,然后在每个组上先替换。实际上,它比实际实现慢得多,但这里的目标是解释如果最终需要的不仅仅是第一项,如何使用它来定制输出。

事实上,不会从列表中删除任何项,返回一个包含不同项的新列表。您始终可以自己添加一个扩展方法对其进行排序:
public static iorderenumerable OrderedDistinct(this IEnumerable data){return data.distinct().OrderBy(x=>x);}
操作返回的列表仅包含第一个出现的原始项,而且没有命令。因此,您必须在示例中预期您的预期输出。事实上,不会从列表中删除任何项,而是返回一个包含不同项的新列表。您始终可以自己添加一个扩展方法对其进行排序:
public static iorderenumerable OrderedDistinct(this IEnumerable data){return data.distinct().OrderBy(x=>x);}
使用
Distinct
操作返回的列表仅包含第一个出现的原始项,并且没有排序。因此,您必须在示例中预期预期的输出。
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;
            }
        }
    }
}