No hay manera "Linqy" incorporado (puede agrupar, pero sería muy ineficiente), pero eso no significa que no pueda hacer su propio camino:
public static IEnumerable<T> TakeDistinctByKey<T, TKey>(
this IEnumerable<T> source,
Func<T, TKey> keyFunc,
int count)
{
if (keyFunc == null)
throw new ArgumentNullException("keyFunc");
if (count <= 0)
yield break;
int currentCount = 0;
TKey lastKey = default(TKey);
bool isFirst = true;
foreach (T item in source)
{
yield return item;
TKey key = keyFunc(item);
if (!isFirst && (key != lastKey))
currentCount++;
if (currentCount > count)
yield break;
isFirst = false;
lastKey = key;
}
}
Entonces se puede invocar con esto:
var items = cache.TakeDistinctByKey(rec => rec.Id, 20);
Si tiene claves compuestas o algo así que fácilmente se podría extender el método anterior para tomar una IEqualityComparer<TKey>
como argumento.
También tenga en cuenta que esto depende de que los elementos estén ordenados por clave.Si no es así, usted podría o bien cambia el algoritmo anterior para utilizar un HashSet<TKey>
en lugar de un recuento y último elemento de comparación directa, o invoca con este lugar:
var items = cache.OrderBy(rec => rec.Id).TakeDistinctByKey(rec => rec.Id, 20);
Editar - También me gusta señalar que en SQL utilizaría una consulta ROW_NUMBER
o un CTE recursivo, según los requisitos de rendimiento; una combinación + distinta es no el método más eficiente. Si su caché está en orden ordenado (o si puede cambiarlo para que esté en orden), el método anterior será de lejos el más barato en términos de memoria y tiempo de ejecución.
Esto es genial. Trabajos. LINQy. Probablemente no sea más rápido que el original, puede ser más lento según lo que ocurra con GroupBy. – David
Siempre será un poco más lento que el original porque tiene que hacer un pase completo la primera vez; el original puede detenerse cuando golpea * n * elementos. Probablemente no sea un problema importante si la lista es pequeña. – Aaronaught
@Aaronaught: Pero el original tiene que hacer un pase completo en la segunda consulta, * y * realizar una búsqueda 'Contiene' en cada paso. Eso podría ser un asesino de rendimiento real. Por supuesto, la única manera de saber con seguridad es comparar con datos del mundo real. – LukeH