2010-04-27 96 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)); 
} 
相關問題