score:8

Accepted answer

Just use this for grouping:

var results = transactions
.GroupBy(p => p.Buyer.UserID)
.Where(x=>x.Count()>1)
.Select(x=> new List<Transaction>(x));

This should produce your List<List<Transaction> with repeated users from the main list. LINQ is not really the right tool to modify a collection while iterating over it. If you really need it, do:

var results = transactions.ToList()
.GroupBy(p => p.Buyer.UserID)
.Where(x=>x.Count()>1)
.Select(x=> 
{
    foreach(var item in x)
        transactions.Remove(item);
    return new List<Transaction>(x);
});

Notice that a copy of transactions list is made to execute the query on ( transactions.ToList() and remove operations are made on the original list. Hope that helped.

score:0

No you are getting an IEnumerable<IGrouping<TKey, TSource>> See: MSDN Group By

So basically it returns a list of groups. The group contains the key where it is grouped on and the element which is the list of items which belongs to the group

The List

  • Group 1
    • Group Key
    • Items (list of your objects)
  • Group 2
    • Group Key
    • Items (list of your objects)

Nice explanation: https://www.udemy.com/blog/linq-group-by/

score:3

Try this :

var dic = _transactions.GroupBy(t => t.Buyer.UserID).ToDictionary(t => t.Key, t => t.ToList());

GroupBy returns a

IEnumerable<IGrouping<TKey, TSource>>

Each IGrouping<> contains as Key, the group criteria, and each IGrouping is enumerable (you list the grouped values)

Since, the question change :

Don't create anonymous types in the GroupBy delegates (no new {...}) Instead, directly target the property (because internally, GroupBy uses equality to group things, and since you create a new anonymous object, there will be nothing grouped, since each new object is a different one)

.GroupBy(o => o.Buyer.UserID, o.ToList) 

Moreover,

Select(p => p) 

does nothing, it's an identity function. It's useless.

If what you want is a List of List, I think you can directly use a Dictionary. (see the first part of my answer) You can enumerate a dictionary in the same way you enumerate a List. And add/remove/replace items in it.

The Dictionary returned will be of type :

Dictionary<int,List<Transactions>> dic =....

With Key = UserId, and for each key, a List of transactions. Moreover, it's really faster than a List of List, since you can directly access the transactions :

int userId = 42;
List<Transactions> transactions = dic[userId];

score:2

Group by in LINQ.

This has answer to your query.

var results = transactions.GroupBy(p => p.Buyer.UserID,
                         (key, g) => new { UserID = key, Cars = g.ToList() });

score:1

If I understand correctly,

You have a transaction list, and a transaction list of lists.

You need to group the latter, by the userId, where the value will be the transactions that correspond to that user.

If that's the case, I prepared a small sample that may help.

good luck

public class Transaction
{
    public Buyer Buyer { get; set; }
}

public class Buyer
{
    public int UserID { get; set; }
}


[TestMethod]
public void Test()
{

    var t1 = new Transaction { Buyer = new Buyer { UserID = 1 } };
    var t2 = new Transaction { Buyer = new Buyer { UserID = 2 } };
    var t3 = new Transaction { Buyer = new Buyer { UserID = 3 } };
    var t4 = new Transaction { Buyer = new Buyer { UserID = 1 } };
    var t5 = new Transaction { Buyer = new Buyer { UserID = 3 } };

    var tList1 = new List<Transaction> { t1, t2, t3 };
    var tList2 = new List<Transaction> { t4, t5 };

    var tLists = new List<List<Transaction>> { tList1 , tList2};

    var result = tLists.
        SelectMany(o => o).
        GroupBy(o =>  new 
        {
            UserId = o.Buyer.UserID
        },
        (key, items) => new
        {
            UserId = key.UserId,
            Transactions = items.Select(p => p).ToList()
        }).
        ToList();
}

This is an updated solution to the edit by the author:

    var transactions = new List<Transaction>
    {
        new Transaction { Buyer = new Buyer { UserID = 1 } },
        new Transaction { Buyer = new Buyer { UserID = 2 } },
        new Transaction { Buyer = new Buyer { UserID = 3 } },
        new Transaction { Buyer = new Buyer { UserID = 1 } },
        new Transaction { Buyer = new Buyer { UserID = 3 } }
    };

    var result = transactions.
        Select(o => o).
        GroupBy(o => new
        {
            UserId = o.Buyer.UserID
        },
        (key, items) => new
        {
            //UserId = key.UserId,
            Transactions = items.Select(p => p).ToList()
        }).
        ToList();

Related Articles