LINQ Count() пока, это более эффективно?
Скажем, я хочу проверить, есть ли в коллекции по крайней мере N элементов.
Это лучше, чем делать?
Count() >= N
Использование:
public static bool AtLeast<T>(this IEnumerable<T> enumerable, int max)
{
int count = 0;
return enumerable.Any(item => ++count >= max);
}
Или даже
public static bool Equals<T>(this IEnumerable<T> enumerable, int amount)
{
return enumerable.Take(amount).Count() == amount;
}
Как я могу сравнить это?
/// <summary>
/// Returns whether the enumerable has at least the provided amount of elements.
/// </summary>
public static bool HasAtLeast<T>(this IEnumerable<T> enumerable, int amount)
{
return enumerable.Take(amount).Count() == amount;
}
/// <summary>
/// Returns whether the enumerable has at most the provided amount of elements.
/// </summary>
public static bool HasAtMost<T>(this IEnumerable<T> enumerable, int amount)
{
return enumerable.Take(amount + 1).Count() <= amount;
}
Ответы
Ответ 1
Есть несколько хорошо документированных оптимизаций, встроенных в метод .Count()
. В частности, если ваш перечислимый тип ICollection
, .Count()
будет работать с постоянным временем, так как он будет использовать свойство ICollection
.Count
.
Однако в общем случае он будет перебирать все IEnumerable
, чтобы получить счетчик. Если у вас нет ICollection
, вам будет лучше использовать любой из двух предложенных методов, если элементов больше N. Для относительной производительности этих двух, вам придется профилировать их, как предложили другие.
Ответ 2
var list = Enumerable.Range(1, 1000000);
var t = new Stopwatch();
t.Restart();
var count = list.Count() > 100000;
t.Stop();
PrintTime(t, count);
t.Restart();
var atLeast = list.AtLeast(100000);
t.Stop();
PrintTime(t, atLeast);
t.Restart();
var equals = list.Equalss(100000);
t.Stop();
PrintTime(t, equals);
Результаты, когда PrintTime() печатает отметки таймера:
True 20818
True 8774
True 8688