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

Эффективный Linq Enumerable 'Count() == 1' test

Подобно этому question, но перефразирован для Linq:

Вы можете использовать Enumerable<T>.Any(), чтобы проверить, содержит ли перечисляемые данные. Но какой эффективный способ проверить, содержит ли перечислимое значение единственное значение (т.е. Enumerable<T>.Count() == 1) или больше одного значения (т.е. Enumerable<T>.Count() > 1) без использования дорогостоящей операции счета?

4b9b3361

Ответ 1

int constrainedCount = yourSequence.Take(2).Count();

// if constrainedCount == 0 then the sequence is empty
// if constrainedCount == 1 then the sequence contains a single element
// if constrainedCount == 2 then the sequence has more than one element

Ответ 2

Один из способов - написать новый метод расширения

public static bool IsSingle<T>(this IEnumerable<T> enumerable) {
  using (var enumerator = enumerable.GetEnumerator()) {
    if (!enumerator.MoveNext()) {
      return false;
    }
    return !enumerator.MoveNext();
  }
}

Ответ 3

Этот код использует LukeH отличный ответ и расширяет его как расширение IEnumerable, чтобы ваш код мог работать в терминах None, One и Many, а не 0, 1 и 2.

public enum Multiplicity
{
    None,
    One,
    Many,
}

В статическом классе, например. EnumerableExtensions:

public static Multiplicity Multiplicity<TElement>(this IEnumerable<TElement> @this)
{
    switch (@this.Take(2).Count())
    {
        case 0: return General.Multiplicity.None;
        case 1: return General.Multiplicity.One;
        case 2: return General.Multiplicity.Many;
        default: throw new Exception("WTF‽");
    }
}

Ответ 4

Другой способ:

bool containsMoreThanOneElement = yourSequence.Skip(1).Any();

Или для ровно 1 элемента:

bool containsOneElement = yourSequence.Any() && !yourSequence.Skip(1).Any();

Ответ 5

Эффективный тест Count() == n:

public static bool CountIsEqualTo<T>(this IEnumerable<T> enumerable, int c) 
{
    using (var enumerator = enumerable.GetEnumerator()) 
    {
        for(var i = 0; i < c ; i++)
            if (!enumerator.MoveNext()) 
                return false;

        return !enumerator.MoveNext();
    }
}

Ответ 6

С linq для объектов SingleOrDefault бросает, если есть более одного элемента, поэтому вам, вероятно, лучше всего, если вы откажетесь от своих собственных.

РЕДАКТИРОВАТЬ: Теперь я видел ответ LukeH, и я должен сказать, что я предпочитаю это. Хотел бы я подумать об этом сам!