【问题标题】:How to find all duplicate from a List<string>? [duplicate]如何从 List<string> 中查找所有重复项? [复制]
【发布时间】:2011-01-02 12:02:54
【问题描述】:

我有一个List&lt;string&gt;,其中有一些重复的单词。我需要找到所有重复的单词。

有什么技巧可以全部搞定吗?

【问题讨论】:

  • @nawfal 我没有看到这里提到的 Linq...

标签: c# list duplicates


【解决方案1】:

在 .NET framework 3.5 及更高版本中,您可以使用 Enumerable.GroupBy 返回重复键的可枚举,然后过滤掉任何计数为

var duplicateKeys = list.GroupBy(x => x)
                        .Where(group => group.Count() > 1)
                        .Select(group => group.Key);

【讨论】:

  • 这会将所有行按其值分组,而不是重复...您仍然必须按Count() &gt; 1 过滤。另外,我理解问题的方式,每行包含几个单词,OP想要重复的单词(但也许我误解了这个问题)
  • @Thomas:是的,代码不完整,这只是第一步。如果他只想要重复的,他可以使用Where,比如list.GroupBy(x =&gt; x).Where(group =&gt; group.Count() &gt; 1).Select(group =&gt; Group.Key).ToList()
【解决方案2】:

如果您使用的是 LINQ,则可以使用以下查询:

var duplicateItems = from x in list
                     group x by x into grouped
                     where grouped.Count() > 1
                     select grouped.Key;

或者,如果您更喜欢没有语法糖:

var duplicateItems = list.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key);

这会将所有相同的元素分组,然后过滤到具有多个元素的组。最后它只从这些组中选择键,因为您不需要计数。

如果您不想使用 LINQ,可以使用此扩展方法:

public void SomeMethod {
    var duplicateItems = list.GetDuplicates();
    …
}

public static IEnumerable<T> GetDuplicates<T>(this IEnumerable<T> source) {
    HashSet<T> itemsSeen = new HashSet<T>();
    HashSet<T> itemsYielded = new HashSet<T>();

    foreach (T item in source) {
        if (!itemsSeen.Add(item)) {
            if (itemsYielded.Add(item)) {
                yield return item;
            }
        }
    }
}

这会跟踪它看到和产生的项目。如果它以前没有看到过一个项目,它会将它添加到已看到的项目列表中,否则它会忽略它。如果它之前没有产生过一个项目,它会产生它,否则它会忽略它。

【讨论】:

  • +1 用于 HashSet。我认为在内部(由于排序和东西)它执行更快的搜索。
  • PMSL @ '没有语法糖'。这确实是 LINQ 方法语法的另一个名称。
  • 如果你不需要跟踪itemsSeen那么循环可以简化为:foreach (T item in source) { if (!itemsYielded.Add(item)) { yield return item; } }
【解决方案3】:

并且没有 LINQ:

string[] ss = {"1","1","1"};

var myList = new List<string>();
var duplicates = new List<string>();

foreach (var s in ss)
{
   if (!myList.Contains(s))
      myList.Add(s);
   else
      duplicates.Add(s);
}

// show list without duplicates 
foreach (var s in myList)
   Console.WriteLine(s);

// show duplicates list
foreach (var s in duplicates)
   Console.WriteLine(s);

【讨论】:

  • 当一个人可以在没有开销的情况下声明时为什么要使用 var?
  • var 中没有“开销”。
【解决方案4】:

如果您正在寻找更通用的方法:

public static List<U> FindDuplicates<T, U>(this List<T> list, Func<T, U> keySelector)
    {
        return list.GroupBy(keySelector)
            .Where(group => group.Count() > 1)
            .Select(group => group.Key).ToList();
    }

编辑:这是一个例子:

public class Person {
    public string Name {get;set;}
    public int Age {get;set;}
}

List<Person> list = new List<Person>() { new Person() { Name = "John", Age = 22 }, new Person() { Name = "John", Age = 30 }, new Person() { Name = "Jack", Age = 30 } };

var duplicateNames = list.FindDuplicates(p => p.Name);
var duplicateAges = list.FindDuplicates(p => p.Age);

foreach(var dupName in duplicateNames) {
    Console.WriteLine(dupName); // Will print out John
}

foreach(var dupAge in duplicateAges) {
    Console.WriteLine(dupAge); // Will print out 30
}

【讨论】:

  • 你能解释一下吗?和 ?我们需要包含一些命名空间吗?还是我们需要用正确类型的对象替换它们?
  • T 和 U 是方法定义中的泛型类型。您可以在调用方法时替换它们,或者像在我的示例中那样推断它们:list.FindDuplicates(p => p.Name): T -> Person; U -> 字符串; list.FindDuplicates(p => p.Age): T -> Person; U -> int;
【解决方案5】:

当然是使用 LINQ。 下面的代码将为您提供字符串形式的项目字典,以及源列表中每个项目的计数。

var item2ItemCount = list.GroupBy(item => item).ToDictionary(x=>x.Key,x=>x.Count());

【讨论】:

    【解决方案6】:

    对于它的价值,这是我的方式:

    List<string> list = new List<string>(new string[] { "cat", "Dog", "parrot", "dog", "parrot", "goat", "parrot", "horse", "goat" });
    Dictionary<string, int> wordCount = new Dictionary<string, int>();
    
    //count them all:
    list.ForEach(word =>
    {
        string key = word.ToLower();
        if (!wordCount.ContainsKey(key))
            wordCount.Add(key, 0);
        wordCount[key]++;
    });
    
    //remove words appearing only once:
    wordCount.Keys.ToList().FindAll(word => wordCount[word] == 1).ForEach(key => wordCount.Remove(key));
    
    Console.WriteLine(string.Format("Found {0} duplicates in the list:", wordCount.Count));
    wordCount.Keys.ToList().ForEach(key => Console.WriteLine(string.Format("{0} appears {1} times", key, wordCount[key])));
    

    【讨论】:

      【解决方案7】:

      我假设您列表中的每个字符串都包含几个单词,如果不正确,请告诉我。

      List<string> list = File.RealAllLines("foobar.txt").ToList();
      
      var words = from line in list
                  from word in line.Split(new[] { ' ', ';', ',', '.', ':', '(', ')' }, StringSplitOptions.RemoveEmptyEntries)
                  select word;
      
      var duplicateWords = from w in words
                           group w by w.ToLower() into g
                           where g.Count() > 1
                           select new
                           {
                               Word = g.Key,
                               Count = g.Count()
                           }
      

      【讨论】:

        【解决方案8】:

        我使用类似的方法来检查字符串中的重复条目:

        public static IEnumerable<string> CheckForDuplicated(IEnumerable<string> listString)
        {
            List<string> duplicateKeys = new List<string>();
            List<string> notDuplicateKeys = new List<string>();
            foreach (var text in listString)
            {
                if (notDuplicateKeys.Contains(text))
                {
                    duplicateKeys.Add(text);
                }
                else
                {
                    notDuplicateKeys.Add(text);
                }
            }
            return duplicateKeys;
        }
        

        也许这不是最简短或最优雅的方式,但我认为这是非常可读的。

        【讨论】:

          【解决方案9】:
              lblrepeated.Text = ""; 
              string value = txtInput.Text;
              char[] arr = value.ToCharArray();
              char[] crr=new char[1];        
             int count1 = 0;        
              for (int i = 0; i < arr.Length; i++)
              {
                  int count = 0;  
                  char letter=arr[i];
                  for (int j = 0; j < arr.Length; j++)
                  {
                      char letter3 = arr[j];
                          if (letter == letter3)
                          {
                              count++;
                          }                    
                  }
                  if (count1 < count)
                  {
                      Array.Resize<char>(ref crr,0);
                      int count2 = 0;
                      for(int l = 0;l < crr.Length;l++)
                      {
                          if (crr[l] == letter)
                              count2++;                    
                      }
          
          
                      if (count2 == 0)
                      {
                          Array.Resize<char>(ref crr, crr.Length + 1);
                          crr[crr.Length-1] = letter;
                      }
          
                      count1 = count;               
                  }
                  else if (count1 == count)
                  {
                      int count2 = 0;
                      for (int l = 0; l < crr.Length; l++)
                      {
                          if (crr[l] == letter)
                              count2++;
                      }
          
          
                      if (count2 == 0)
                      {
                          Array.Resize<char>(ref crr, crr.Length + 1);
                          crr[crr.Length - 1] = letter;
                      }
          
                      count1 = count; 
                  }
              }
          
              for (int k = 0; k < crr.Length; k++)
                  lblrepeated.Text = lblrepeated.Text + crr[k] + count1.ToString();
          

          【讨论】:

          • 我也可以吃点意大利面吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-15
          • 1970-01-01
          • 1970-01-01
          • 2011-11-07
          • 2014-11-11
          • 1970-01-01
          相关资源
          最近更新 更多