【问题标题】:Remove duplicate from large lists efficiently?有效地从大型列表中删除重复项?
【发布时间】:2015-01-17 23:14:52
【问题描述】:

我有一个包含 id 和值的列表,我需要删除 id 重复项。我正在寻找一种在 LINQ 中更可取的有效方式,而不是我的循环和 if 条件。感谢您的帮助和建议。

var list = new List<Tuple<int, double>>();

Current values:
1, 3.6
1, 3.8
2, 5.6
3, 8.1

Wished values:
1, 3.6
2, 5.6
3, 8.1


for (int i = 0; i < list.Count - 1; i++)
{
    if (list[i].Item1 == list[i + 1].Item1)
        list.RemoveAt(i+ 1);
}

【问题讨论】:

  • 当前值和期望值没有区别
  • 现在看,我是在发帖后才注意到的。
  • 我必须对此发表评论......(可能会成为我对 SO 上这些与 LINQ 相关的问题的不满)。为什么你认为 LINQ 版本比简单的 for 循环实现更高效?就执行效率而言,使用.GroupBy.Select.ToDictionary 的公认答案远非高效。 :(那么你在这里寻求什么效率?我不明白。请澄清..我很好奇。
  • @VikasGupta 一些人使用 LINQ 是因为想要更短、更好的可读性和可维护性的代码。我希望这能满足你的好奇心。但是,如果你能帮忙而不是好奇,我认为会是击球手。

标签: c# linq list


【解决方案1】:

如果 Id 和 Values 与另一个相同。它将从列表中删除该项目。

distinctList = list.Distinct().ToList();

如果您可以将 Tuple 转换为 Dictionary

试试这个:如果只有 Id 是重复的,则从列表中删除该项目。它不会考虑值重复。

var distinctDictionary = list.GroupBy(id => id.Item1)
                         .Select(group => group.First())
                         .ToDictionary(id => id.Item1, val => val.Item2);

查看屏幕截图:

解决方案 1:

解决方案 2:

【讨论】:

  • 只比较ID还是整行?
  • 仅 Id,不考虑值。
  • 例如:如果Id and Values are same 是另一个。它将从列表中删除该项目。
  • 第二个解决方案仅在 Id 重复的情况下起作用。
  • 好的,只是 ID 相同,值不同。看我的例子。无论如何,在我的读取应用程序中,我只需要 Id,如果我使用您的第二个示例(distinctDictionary)然后将 distinctDictionary 转换为仅采用 Id 的列表呢?
【解决方案2】:

为什么你是带有元组的List?对于请求的功能,我会使用Dictionary,这样您就不会有重复项。

【讨论】:

  • 这只是一个例子。在我的情况下,我有一个函数对它们进行插值。
  • @doro - 从您提供的内容来看,您似乎有一个“识别”数据,然后还有“其他”数据。在您显示的代码中,“识别”数据是元组的Item1,“其他”是Item2。在本例中为intdouble,但也可以是longDateTime,或GuidSomeHugeClass。现在您有了这些对的列表,并且您想从中“删除重复项”。基本上,对于每个“识别”事物,您只需要 一个“其他事物”。这是key -&gt; value,这就是Dictionaries 的用途。
  • 我刚刚解释了我为什么使用 List。但是,关键是如何删除 ids 重复。我还包括了一个循环,如果它可以工作,但我正在寻找更好的方法。
【解决方案3】:

DistinctByKey = list.Select(x => x.Keys).Distinct();

DistinctByValue= DistinctByKey.Select(x => x.Values).Distinct();

【讨论】:

    【解决方案4】:

    鉴于您认为 LINQ 通常更具可读性/可维护性并且通常与效率相当,我提出了以下使用 LINQ 的解决方案,并且(恕我直言,与迄今为止提出的其他解决方案相比)执行效率更高 -

    list = list.Where((entry, i) => i == 0 || entry.Item1 != list[i - 1].Item1).ToList();
    

    【讨论】:

    • 除了我原来的问题之外,还有什么办法 list = ... 只包含 ids(只有 item1)?
    • var list2 = list.Select(item =&gt; item.Item1).Distinct().ToList();
    • @Vikas - 您的解决方案很棒,但如果您只检查前一个元素,您可能需要先对列表进行排序(如果列表尚未排序)。 list = list.OrderBy(item =&gt; item.Item1).ToList();
    • @Corak 同意.. 但我认为问题中所述的示例(以及当前的 for 循环实现)清楚地表明,可以针对这种特定情况做出以下假设 - 1. 它是一个列表(具体来说,支持索引,否则无法使用索引器)。 2. 列表已经排序。 3.列表中的对象类型还没有实现合适的Comparer/Equatable,有很多:(,接口支持场景。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 2013-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多