C#确定列表中的重复项

时间:2011-02-22 15:59:45

标签: c# linq algorithm list generics

要求:在未排序的列表中,确定是否存在重复项。我这样做的典型方法是n平方嵌套循环。我想知道其他人如何解决这个问题。 Linq有一种优雅,高性能的方法吗?需要lambda或比较器的通用的东西会很好。

11 个答案:

答案 0 :(得分:124)

除非我遗漏了某些东西,否则你应该能够使用Distinct()来解决一些简单的问题。虽然它不会是你能提出的最复杂的实现,但它会告诉你是否删除了任何重复项:

var list = new List<string>();

// Fill the list

if(list.Count != list.Distinct().Count())
{
     // Duplicates exist
}

答案 1 :(得分:42)

根据Eric White关于如何Find Duplicates using LINQ

的文章
  

查找重复项的简单方法是编写按标识符分组的查询,然后筛选具有多个成员的组。在下面的示例中,我们想知道4和3是重复的:

     
int[] listOfItems = new[] { 4, 2, 3, 1, 6, 4, 3 };
var duplicates = listOfItems
    .GroupBy(i => i)
    .Where(g => g.Count() > 1)
    .Select(g => g.Key);
foreach (var d in duplicates)
    Console.WriteLine(d); // 4,3

答案 2 :(得分:18)

为了在列表的早期存在重复项时允许短路,您可以添加HashSet<T>并检查其.Add方法的返回值。

通过使用.Any,您可以在找到副本时立即将枚举短路。

这是C#和VB中的LINQ扩展方法:

CSHARP:

public static bool ContainsDuplicates<T>(this IEnumerable<T> enumerable)
{
    var knownKeys = new HashSet<T>();
    return enumerable.Any(item => !knownKeys.Add(item));
}

Visual Basic:

<Extension>
Public Function ContainsDuplicates(Of T)(ByVal enumerable As IEnumerable(Of T)) As Boolean
    Dim knownKeys As New HashSet(Of T)
    Return enumerable.Any(Function(item) Not knownKeys.Add(item))
End Function

注意:要检查是否有没有重复项,只需将Any更改为All

答案 3 :(得分:13)

将所有项目放在一个集合中,如果该集合的计数与列表的计数不同,则会有重复。

bool hasDuplicates<T>(List<T> myList) {
    var hs = new HashSet<T>();

    for (var i = 0; i < myList.Count; ++i) {
        if (!hs.Add(myList[i])) return true;
    }
    return false;
}

应该比Distinct更有效,因为不需要遍历所有列表。

答案 4 :(得分:2)

沿着这些方向的东西相对简单,并且会为您提供重复的计数。

var something = new List<string>() { "One", "One", "Two", "Three" };

var dictionary = new Dictionary<string, int>();

something.ForEach(s =>
    {
        if (dictionary.ContainsKey(s))
        {
            dictionary[s]++;
        }
        else
        {
            dictionary[s] = 1;
        }
    });

我想这与Distinct的实现相似,虽然我不确定。

答案 5 :(得分:2)

您可以使用IEnumerable.GroupBy方法。

var list = new List<string> {"1", "2","3", "1", "2"};
var hasDuplicates = list.GroupBy(x => x).Any(x => x.Skip(1).Any());

答案 6 :(得分:1)

您可以对IEnumerable使用Distinct()扩展方法

答案 7 :(得分:1)

如果使用整数或排序良好的集合,请使用二叉树表示O(nlog n)性能。

或者,找到另一种更快的排序方法,然后只需检查每个值是否与前一个值不同。

答案 8 :(得分:1)

Enumerable.AnyHashSet.Add一起使用,如:

List<string> list = new List<string> {"A", "A", "B", "C", "D"};
HashSet<string> hashSet = new HashSet<string>();
if(list.Any(r => !hashSet.Add(r)))
{
   //duplicate exists. 
}
如果该项目已存在于HashSet.Add中,则

false将返回HashSet。这不会迭代整个列表。

答案 9 :(得分:0)

您可以使用Distinct()语句查找唯一记录。然后与原始通用列表进行比较:

  if (dgCoil.ItemsSource.Cast<BLL.Coil>().ToList().Count != dgCoil.ItemsSource.Cast<BLL.Coil>().Select(c => c.CoilNo).Distinct().Count())
  {    
    //Duplicate detected !!
    return;
  }

答案 10 :(得分:-1)

还没有看到有人这样做,所以这里是我刚写的一个小程序。这很简单。使用Contains(),虽然我不知道这种方法的可扩展性如何。

       Console.WriteLine("Please enter 5 unique numbers....");
        List<int> uniqueNums = new List<int>() { };
        while (uniqueNums.Count < 5)
        {
            int input = Convert.ToInt32(Console.ReadLine());
            if (uniqueNums.Contains(input))
            {
                Console.WriteLine("Add a different number");
            }
            uniqueNums.Add(input);
        }
        uniqueNums.Sort();
        foreach (var n in uniqueNums)
        {
            Console.WriteLine(n);
        }