I'm creating a function that will take some IEnumerable, conduct grouping, ordering, take some top N elements, and return a list of those elements. It may likely do more later on, that's why I want to make it into a function and not just use LINQ directly.

I rely on anonymous delegate to specify which members of type T will be used to group and sort the collection.

    public IEnumerable<T> GetList(IEnumerable<T> collection, Func<T, object> groupBy, Func<T, object> orderBy, int howMany)
    {
        var group = collection
            .GroupBy(groupBy)
            .Select(x => x.OrderBy(orderBy).Take(howMany))
            .Aggregate((l1, l2) => l1.Concat(l2));

        return group.ToList();
    }

And use like this:

        new CollectionGroupPicker<NumericDomainObject>().GetList(list, x => x.GroupableField, x => x.OrderableField, 2).ToList();

My question is - is there a better way to pass which member of type T I will use to group and sort by? I'm using object here, but is there a better way?

有帮助吗?

解决方案

Instead of specifying object you should specify the group and select keys as generic parameters. Their type will be automatically inferred from usage and the caller can specify a lambda with any return type.

public IEnumerable<T> GetList<TGroupKey, TOrderKey>(IEnumerable<T> collection, 
                                                    Func<T, TGroupKey> groupBy, 
                                                    Func<T, TOrderKey> orderBy, 
                                                    int howMany)
{
    var group = collection
        .GroupBy(groupBy)
        .Select(x => x.OrderBy(orderBy).Take(howMany))
        .Aggregate((l1, l2) => l1.Concat(l2));
    return group.ToList();
}

其他提示

I agree with Samuel use the generic parmater types. Also, why not use SelectMany to flatten the result, and perhaps make it an extension method?

static class GetListExtensionMethods
{
    public static IEnumerable<T> GetList<T, TGroupingField, TOrderingField>(this IEnumerable<T> collection, Func<T, TGroupingField> groupBy, Func<T, TOrderingField> orderBy, int howMany)
    {
        var group = collection
            .GroupBy(groupBy)
            .SelectMany(x => x.OrderBy(orderBy).Take(howMany));
        return group.ToList();
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top