【问题标题】:The order of returning items in the resultant List when using List.Distinct()使用 List.Distinct() 时返回结果列表中项目的顺序
【发布时间】:2017-01-15 01:39:50
【问题描述】:

在我的下图中应用DISTINCT.ToList() 时,哪些项目将从结果列表中删除? 重复项中的第一个条目(即第一个添加到列表中的条目)是否保留在返回的新列表中?如果没有,有没有办法让DISTINCT.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

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

【问题讨论】:

  • 事实上,不会从列表中删除任何项目,而是返回一个包含不同项目的新列表。
  • 您始终可以自己添加一个扩展方法来订购它:public static IOrderedEnumerable<T> OrderedDistinct(this IEnumerable<T> data) { return data.Distinct().OrderBy(x => x); }
  • Distinct操作返回的列表只包含最先出现的原始项,没有排序。所以你必须在你的例子中期待你的预期输出。

标签: c# vb.net list ienumerable


【解决方案1】:

不,您不能使用 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;
            }
        }
    }
}

【讨论】:

    【解决方案2】:

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

    根据您提供的示例,按索引选择第一项在技术上是无关紧要的,因为您将无法知道它是自 Int 结构以来列表中的第一次还是第 100 次出现。

    但这就是说我猜你正在使用自定义对象。在这种情况下,您的订单来自某种排序。在这种情况下,我建议您改为使用GroupBy&lt;&gt;,然后为每个组按您的OrderBy&lt;&gt; 语句订购项目,然后在上面执行First&lt;&gt;

    Group by 和 Distinct 非常接近。 distinct 可以被一个 group by 替换,然后在每个 group 上先替换。实际上它比实际实现要慢得多,但这里的目标是解释如果您最终需要的不仅仅是第一项,如何使用它来自定义输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-10
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      • 2020-07-22
      • 2010-11-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多