Я пытаюсь добавить расширение общего назначения TopN IEnumerable<T>
.TopN as IEnumerable extension
Если параметр положительный, то он совпадает с Take(), но если он отрицательный, то он должен делать то же самое, что и Take(), но затем сохраняет сразу же последовательные значения, соответствующие последнему значению из Take(). (То же, что SQL ТОП н с галстуками)
Это код, у меня есть на данный момент: -
public static class Test
{
public static IEnumerable<TSource> TopN<TSource>(this IEnumerable<TSource> source, int topN)
{
return TopN(source, topN, (v1, v2) => v1.Equals(v2));
}
public static IEnumerable<TSource> TopN<TSource>(this IEnumerable<TSource> source, int topN, Func<TSource, TSource, bool> comparer)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (comparer == null) throw new ArgumentNullException(nameof(comparer));
return topN >= 0
? source.Take(topN)
: TopNWithTiesIterator(source, -topN, comparer);
}
static IEnumerable<TSource> TopNWithTiesIterator<TSource>(this IEnumerable<TSource> source, int topN, Func<TSource, TSource, bool> comparer)
{
var lastItem = default(TSource);
foreach (var item in source)
{
if (topN-- > 0 || comparer(item, lastItem))
{
lastItem = item;
yield return item;
}
else
{
yield break;
}
}
}
}
и вот пример реального мира использования и некоторые другие быстрые тесты я попытался :
if (TopN != 0)
{
var values = new[] { 1, 2, 2, 3 };
Debug.Assert(!values.TopN(0).Any());
Debug.Assert(!values.TopN(0, (v1, v2) => v1 == v2).Any());
Debug.Assert(values.TopN(1, (v1, v2) => v1 == v2).Count() == 1);
Debug.Assert(values.TopN(-1, (v1, v2) => v1 == v2).Count() == 1);
Debug.Assert(values.TopN(2, (v1, v2) => v1 == v2).Count() == 2);
Debug.Assert(values.TopN(-2, (v1, v2) => v1 == v2).Count() == 3);
Debug.Assert(values.TopN(2).Count() == 2);
Debug.Assert(values.TopN(-2).Count() == 3);
// This is how I really want to use it
summaries = summaries.TopN(TopN, (v1, v2) => v1.ClientValue + v1.AdviserValue == v2.ClientValue + v2.AdviserValue);
}
Мой вопрос о том, с помощью Func<TSource, TSource, bool>
, как сравнивающий правильно.
Должен ли я использовать IEqualityComparer<T>
или IEquatable<<T>
или что-то еще?
Попытка изменить этот вопрос, чтобы он не был основан на мнениях. Помогло бы это, если бы я добавил «.. соответствовать существующим стандартам Microsoft»? –