2010-04-27 98 views
8

我有一个List<string>包含重复项,我需要找到每个索引。什么是最优雅的方式来查找C#列表中重复项目的索引

什么是最优雅,有效的方式,而不是遍历所有的项目。我在.NET 4.0上,所以LINQ是一个选项。我做了大量的搜索和连接找到任何东西。

的样本数据:

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

我需要让 “家” 的指标。

+11

列表中有多少项?它是否分类?它是否可排序?你如何比较平等?它是否必须适用于任何数据类型或只是字符串?你为什么要把重复项放在首位呢?你问最优雅和最有效率,但这些往往是对立面;这实际上更重要? – 2010-04-27 05:01:25

+1

你为什么说“除了循环通过项目”?有人必须在某些时候循环浏览这些项目 - 无论是你还是linq,它确实无关紧要。 – Stewart 2010-04-27 05:05:14

回答

19

您可以从包含其索引的每个项目创建一个对象,然后对该值进行分组并过滤出包含多个对象的组。现在你有一个包含文本对象和它们原来的指数分组列表:

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

我喜欢这个解决方案!易于阅读和快速! – 2010-04-27 05:40:01

+0

感谢这是我能找到的最优雅的解决方案 – 2010-06-03 23:47:59

3
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++; 
     } 
    } 
} 
0

如何像这样

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)); 
+0

Interresting,但效率非常低。您应该为列表中的每个项目创建一次而不是一次。为了高效,查找应该是一个HashSet,而不是一个List。 – Guffa 2010-04-27 06:38:30

0

我自己需要找到并从列表中删除重复项字符串。我首先搜索了重复项目的索引,然后使用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)); 
} 
相关问题