Home > Software engineering >  Linq group by with multiple keys
Linq group by with multiple keys

Time:05-18

If I have an IEnumerable, how can I split them using linq to give a list within a list of executions that are unique based on Tenant, UserId, AccountId and Bucket.

I am looking to get a list of lists of the form IEnumerable<(Tenant,UserId,AccountId,Bucket),IEnumerable<TradeExecuted>>.

public class TradeExecuted : INotification
{
    public Guid Tenant { get; init; }
    public UserId UserId { get; init; }
    public string AccountId { get; init; }
    public string Bucket { get; init; }
    /* other fields */
}

I have given the UserId object below, but believe concerns with uniqueness are addressed via the ValueObject per this article.

public class AccountId : ValueObject
{
    public string Account { get; init; }
    public string Broker { get; init; }

    public AccountId(string broker, string account)
    {
        Broker = broker;
        Account = account;
    }

    protected override IEnumerable<object> GetEqualityComponents()
    {
        yield return Broker;
        yield return Account;
    }
}

A dictionary is OK but having a mind freeze with the below:

var splitMessages = messages
        .GroupBy(x => (x.Bucket, x.AccountId, x.Tenant, x.UserId))
        .ToDictionary(key => key.Key);

If easier to get a list of lists, am ok with that also - pointers much appreciated.

CodePudding user response:

Try

var splitMessages = messages
        .GroupBy(x => (x.Bucket, x.AccountId, x.Tenant, x.UserId))
        .ToDictionary(key => key.Key, values = values.Select(s => s);

CodePudding user response:

I'm not sure why you would need to do anything beyond the grouping, GroupBy provides a IEnumerable<IGrouping<TKey,TElement>> which IGrouping is an extension of IEnumerable<out TElement> So as you can see just using GroupBy() provides you with a list of lists.

That is why I could do this.


var splitMessages = messages
    .GroupBy(x => (x.Bucket, x.AccountId, x.Tenant, x.UserId));
var castedMessages = (IEnumerable<IEnumerable<TradeExecuted>>)splitMessages;

I can not say I understand exactly what this form is IEnumerable<(Tenant,UserId,AccountId,Bucket),IEnumerable<TradeExecuted>> IEnumerable is described as having one covariant generic argument. It looks like what you want is exactly what IEnumerable<IGrouping<..>> offers which is a list of lists which has the key


  • Related