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: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();

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: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];

Related Query