【问题标题】:What is the most elegant way to find index of duplicate items in C# List在 C# List 中查找重复项索引的最优雅方法是什么
【发布时间】:2011-02-12 17:06:40
【问题描述】:

我有一个包含重复项的 List<string>,我需要找到每个的索引。

除了遍历所有项目之外,最优雅、最有效的方法是什么。我在 .NET 4.0 上,所以 LINQ 是一个选项。我已经进行了大量的搜索和连接找到任何东西。

样本数据:

var data = new List<string>{"fname", "lname", "home", "home", "company"}();

我需要获取“家”的索引。

【问题讨论】:

  • 列表中有多少项?排序了吗?是否可排序?你如何比较平等?它必须适用于任何数据类型还是只适用于字符串?您为什么首先将重复项放在列表中?你要求最优雅和最有效的,但这些往往是相反的;哪个更重要?
  • 你为什么说“除了遍历项目”?有人必须在某个时候循环遍历这些项目——无论是你还是 linq 都肯定是无关紧要的。

标签: c# search list duplicates


【解决方案1】:

您可以从包含它的索引的每个项目创建一个对象,然后对值进行分组并过滤掉包含多个对象的组。现在您有了一个分组列表,其中包含包含文本及其原始索引的对象:

var duplicates = data
  .Select((t,i) => new { Index = i, Text = t })
  .GroupBy(g => g.Text)
  .Where(g => g.Count() > 1);

【讨论】:

  • 谢谢,这是我能找到的最优雅的解决方案
【解决方案2】:
using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        var data = new List<string> { "fname", "lname", "home", "home", "company" };
        foreach (var duplicate in FindDuplicates(data))
        {
            Console.WriteLine("Duplicate: {0} at index {1}", duplicate.Item1, duplicate.Item2);
        }
    }

    public static IEnumerable<Tuple<T, int>> FindDuplicates<T>(IEnumerable<T> data)
    {
        var hashSet = new HashSet<T>();
        int index = 0;
        foreach (var item in data)
        {
            if (hashSet.Contains(item))
            {
                yield return Tuple.Create(item, index);
            }
            else
            {
                hashSet.Add(item);
            }
            index++;
        }
    }
}

【讨论】:

    【解决方案3】:

    这样的事情怎么样

    var data = new List<string>{"fname", "lname", "home", "home", "company"};
    
                var duplicates = data
                                .Select((x, index) => new { Text = x, index})
                                .Where( x => (  data
                                                .GroupBy(i => i)
                                                .Where(g => g.Count() > 1)
                                                .Select(g => g.Key).ToList()
                                              ).Contains(x.Text));
    

    【讨论】:

    • 很有趣,但效率很低。您应该为列表中的每个项目创建一次查找,而不是一次。为了提高效率,查找应该是 HashSet,而不是 List。
    【解决方案4】:

    我自己需要从字符串列表中查找并删除重复项。我首先搜索重复项的索引,然后使用 LINQ 以功能方式过滤列表,而不改变原始列表:

    public static IEnumerable<string> RemoveDuplicates(IEnumerable<string> items)
    {
        var duplicateIndexes =  items.Select((item, index) => new { item, index })
                                .GroupBy(g => g.item)
                                .Where(g => g.Count() > 1)
                                .SelectMany(g => g.Skip(1), (g, item) => item.index);
        return items.Where((item, index) => !duplicateIndexes.Contains(index));
    }
    

    【讨论】:

      猜你喜欢
      • 2010-10-13
      • 1970-01-01
      • 2011-03-27
      • 2010-11-04
      • 2019-09-18
      • 2011-04-01
      • 2012-07-30
      • 1970-01-01
      相关资源
      最近更新 更多