Подтвердить что ты не робот

Проверьте, являются ли все значения в списке уникальными

У меня есть небольшой список байтов, и я хочу проверить, что все они разные. Например, у меня есть это:

List<byte> theList = new List<byte> { 1,4,3,6,1 };

Какой лучший способ проверить, являются ли все значения различными или нет?

4b9b3361

Ответ 1

bool isUnique = theList.Distinct().Count() == theList.Count();

Ответ 2

Здесь другой подход, который более эффективен, чем Enumerable.Distinct + Enumerable.Count (тем более, если последовательность не является типом коллекции). Он использует HashSet<T>, который устраняет дубликаты, очень эффективен в поиске и имеет свойство count:

var distinctBytes = new HashSet<byte>(theList);
bool allDifferent = distinctBytes.Count == theList.Count;

или другой - более тонкий и эффективный подход:

var diffChecker = new HashSet<byte>();
bool allDifferent = theList.All(diffChecker.Add);

HashSet<T>.Add возвращает false, если элемент не может быть добавлен, поскольку он уже был в HashSet. Enumerable.All останавливается на первом "ложном".

Ответ 3

Хорошо, вот самый эффективный метод, который я могу придумать для использования стандартной .Net

using System;
using System.Collections.Generic;

public static class Extension
{
    public static bool HasDuplicate<T>(
        this IEnumerable<T> source,
        out T firstDuplicate)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }

        var checkBuffer = new HashSet<T>();
        foreach (var t in source)
        {
            if (checkBuffer.Add(t))
            {
                continue;
            }

            firstDuplicate = t;
            return true;
        }

        firstDuplicate = default(T);
        return false;
    }
}

по существу, какова точка перечисления всей последовательности дважды, если все, что вы хотите сделать, это найти первый дубликат.

Я мог бы оптимизировать это больше благодаря специальной оболочке пустых и одиночных последовательностей элементов, но это будет обесцениваться из удобочитаемости/ремонтопригодности с минимальным коэффициентом усиления.

Ответ 4

Существует много решений.

И, без сомнения, более красивые с использованием LINQ называются "juergen d" и "Tim Schmelter".

Но если вы обнажаете "Сложность" и скорость, лучшим решением будет его реализация самостоятельно. Одним из решений будет создание массива размера N (для байта 256). И зациклируйте массив, и на каждой итерации будет проверяться индекс совпадающего числа, если значение равно 1, если это произойдет, это означает, что я уже увеличиваю индекс массива, и поэтому массив не отличается, иначе я увеличим ячейку массива и продолжу проверку.

Ответ 5

И еще одно решение, если вы хотите найти дублированные значения.

var values = new [] { 9, 7, 2, 6, 7, 3, 8, 2 };

var sorted = values.ToList();
sorted.Sort();
for (var index = 1; index < sorted.Count; index++)
{
    var previous = sorted[index - 1];
    var current = sorted[index];
    if (current == previous)
        Console.WriteLine(string.Format("duplicated value: {0}", current));
}

Вывод:

duplicated value: 2
duplicated value: 7

http://rextester.com/SIDG48202