C #: хорошая и эффективная реализация IEnumerable <T>.HasDuplicates - PullRequest
4 голосов
/ 16 июля 2009

Есть ли у кого-нибудь хороший и эффективный метод расширения для определения наличия дубликатов в последовательности элементов?

Полагаю, я мог бы добавить return subjects.Distinct().Count() == subjects.Count() в метод расширения, но вроде бы должен быть лучший способ. Этот метод должен будет считать элементы дважды и отсортировать все элементы distict. Лучшая реализация должна возвращать true для первого найденного дубликата. Есть хорошие предложения?

Я предполагаю, что контур может быть примерно таким:

public static bool HasDuplicates<T>(this IEnumerable<T> subjects)
{
    return subjects.HasDuplicates(EqualityComparer<T>.Default);
}

public static bool HasDuplicates<T>(this IEnumerable<T> subjects, IEqualityComparer<T> comparer)
{
    ...
}

Но не совсем уверен, насколько разумной будет его реализация ...

Ответы [ 3 ]

13 голосов
/ 16 июля 2009
public static bool HasDuplicates<T>(this IEnumerable<T> subjects)
{
    return HasDuplicates(subjects, EqualityComparer<T>.Default);
}

public static bool HasDuplicates<T>(this IEnumerable<T> subjects, IEqualityComparer<T> comparer)
{
    HashSet<T> set = new HashSet<T>(comparer);
    foreach (T item in subjects)
    {
        if (!set.Add(item))
            return true;
    }

    return false;
}
4 голосов
/ 04 июня 2010

Это в производственном коде. Прекрасно работает:

public static bool HasDuplicates<T>(this IEnumerable<T> sequence) {
    var set = new HashSet<T>();
    return !sequence.All(item => set.Add(item));
}
1 голос
/ 16 июля 2009

Я думаю, что самый простой способ расширения заключается в следующем.

public static bool HasDuplicates<T>(this IEnumerable<T> enumerable) {
  var hs = new HashSet<T>();
  foreach ( var cur in enumerable ) {
    if ( !hs.Add(cur) ) {
      return false;
    }
  }
}
...