LINQ c # уникальный элемент в коллекции - PullRequest
2 голосов
/ 08 ноября 2011

У меня есть метод, который должен проверять, есть ли в коллекции ровно один элемент, который остается верным для некоторого предиката (заданного как Func).

public bool ExistsUnique(Func<T, bool> p)
    {
        var tempCol = from i in MyCollection where p(i) select i;  
        return (tempCol.Count() == 1);
    }

Проблема в том, что когда второй элемент, который также имеет место для предиката найдено (например, две одинаковые строки существуют в коллекции), число равно 1. Это означает, что он либо переопределяет первый элемент, либо никогда не добавляет второй, поскольку он уже существует.

Есть идеи, как я могу исправить этот метод? Спасибо / Питер

Ответы [ 4 ]

2 голосов
/ 08 ноября 2011

Вы можете использовать метод Single(), предоставленный LINQ, следующим образом:

public bool ExistsUnique(Func<T, bool> p)
{
    try
    {
        var temp = myCollection.Single(x => p(x));
    }
    catch(Exception e)
    {
        // log exception
        return false;
    }

    return true;
}

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

С http://msdn.microsoft.com/en-us/library/bb535118.aspx

РЕДАКТИРОВАТЬ

Чтобы не вызывать исключение, вы также можете использовать SingleOrDefault() метод:

public bool ExistsUnique(Func<T, bool> p)
{
    return myCollection.SingleOrDefault(x => p(x)) != null;
}
1 голос
/ 08 ноября 2011

Должна быть другая проблема. Я подозреваю, что ваш предикат. Например, это возвращает счет 2, как и ожидалось:

        List<string> MyCollection = new List<string>()
        {
            "hello",
            "hello"
        };
        var tempCol = from i in MyCollection where i == "hello" select i;
        int count = tempCol.Count();

Я сомневаюсь, что ты тоже так называешь. Следующие работы (возвращает false):

    static List<string> MyCollection = new List<string>()
        {
            "hello",
            "hello"
        };

    static bool ExistsUnique(Func<string, bool> p)
    {
        var tempCol = from i in MyCollection where p(i) select i;
        return tempCol.Count() == 1;
    }

    static void DoIt()
    {
        bool isUnique = ExistsUnique((s) => s.Equals("hello"));
        Console.WriteLine(isUnique);
    }
1 голос
/ 08 ноября 2011

Вы уверены, что tempCol полностью прошел через MyCollection? Count() - это метод, который вызывает полный цикл, или он ленивый?

Дает ли, например, tempCol.ToList().Count правильный результат?

0 голосов
/ 09 ноября 2011

Эта реализация сделает так, что вам не нужно будет фактически перечислять всю коллекцию, поэтому вы сэкономите некоторое время выполнения.

public bool ExistsUnique(Func<T, bool> p)
{
    return MyCollection.Where(i => p(i)).Take(2).Count() == 1;
}

Take(2) ограничивает Count только перечислениемпервые два, отвечающие критериям.

...